javaSE------2.面向对象

JavaSE面向对象基础总结

第11章 面向对象基础

1. 类和对象

1.1 类的概述

1.1.1 什么是对象

客观存在的事物皆为对象 ,所以我们也常常说万物皆对象。

1.1.2 什么是类

类是对现实生活中一类具有共同属性和行为的事物的抽象

1.1.3.类的组成

属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)

行为:指事物能执行的操作,例如:手机事物(打电话,发短信)

1.1.4 类和对象的关系

简单来说:类是对象的抽象,对象是类的实体

1.2 类的定义

类的重要性:类是JAVA程序的基本组成单位

1.2.1类的组成

属性:在类中通过成员变量来体现(类中方法外的变量)

行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)
2.类的定义步骤

public class 类名{
		//成员变量
		变量1的数据类型  变量1;
		变量2的数据类型  变量2.........
		//成员方法(定义成员方法时 去掉  static)
		方法1;
		方法2} 

1.3 对象的使用

1.创建对象的格式

类名 对象名 = new 类名();   //在main方法中创建

Tip: 创建对象也可以叫:实例化一个对象、把类实例化

注意
1.new会给类里面的成员变量赋为默认值
2.如果sout输出对象名,则会得到地址值

2.调用成员的格式
对象名.成员变量
对象名.成员方法();

注意:调用者即为main方法中的 对象名(作用是为了提供地址值)

1.4 对象内存图

(1)多个对象在堆内存中,都有不同的内存划分:
a.成员变量存储在各自的内存区域中
b.成员方法多个对象可以共用一个

(2)多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的)

Phone s1=new Phone();  //创建s1的对象
Phone s2=s1;   //(把s1的地址值赋值给了s2后,地址值相同)

只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。

1.5 成员变量和局部变量

成员变量和局部变量的区别
1.类中位置不同:
成员变量(类中方法外)
局部变量(方法内部或方法声明上(方法形参位置))
2.内存中位置不同:
成员变量(堆内存)
局部变量(栈内存)
3.生命周期不同:
成员变量(随着对象的存在而存在,随着对象的消失而消失)
局部变量(随着方法的调用而存在,随着方法的调用完毕而消失)
4.初始化值不同
成员变量(有默认初始化值)
局部变量(没有默认初始化值,必须先定义,赋值才能使用)

2. 封装

2.1 封装思想

1.封装概述:
是面向对象三大特征之一(封装,继承,多态)是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的

2.封装原则:
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问成员变量

3.封装好处:
通过方法来控制成员变量的操作,提高了代码的安全性把代码用方法进行封装,提高了代码的复用性

2.2 private关键字

1.private是一个修饰符,可以用来修饰成员(成员变量,成员方法)

2.被private修饰的成员,只能在本类进行访问,针对private修饰的成员变量,setXxx和getXxx方法都属于成员方法,定义方法时都不加static

如果需要被其他类使用,提供相应的操作 (变量名首字母大写)

A:提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰-------不需要返回值(写void即可),需要参数

public void setXxx(数据类型1 变量名1 , 数据类型2 变量名2){
	this.变量名=变量名;
}

B:提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰 -----需要返回值

public 返回值类型 getXxx(){
	return 返回值;
}

自动生成: Alt+Insert----可以选择生成构造方法,get和set成员方法

2.3 this关键字

1.this修饰的变量用于指代成员变量,其主要作用是解决局部变量隐藏成员变量时(即重名问题)

2.方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量

3.方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量
什么时候用this-------解决局部变量隐藏成员变量时(同名)

this内存原理

this代表当前调用方法的引用,哪个对象调用的方法,this就代表哪一个对象

3. 构造方法

3.1 构造方法概述

构造方法是一种特殊的方法

作用:
主要是完成对象数据的初始化

初始化步骤
a.默认初始化
b.显示初始化
c.构造初始化

格式:

public class 类名{ 

			修饰符 类名(参数){ //注意:此处只填参数,没有参数类型
			}
}

3.2 构造方法的注意事项

1.构造方法的创建
如果没有定义构造方法,系统将给出一个默认的无参数构造方法

如果定义了构造方法,系统将不再提供默认的构造方法

2.构造方法的重载
如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法

3.推荐的使用方式
无论是否使用,都手工书写无参数构造方法

4.重要功能!
可以使用带参构造,为成员变量赋值

3.3 标准类制作

1.成员变量
使用private

2.构造方法
提供一个无参方法
提供一个带多个参数的构造方法

3.成员方法
提供每一个成员变量对应的setXxx()/getXxx()
提供一个显示对象信息的show()

标准类示例:
public class Student{
//1.成员变量(使用private修饰)
	    private String name;
	    private int age;

//2.构造方法
	//定义一个无参数构造方法
        public Student(){ }
    //定义一个带参数构造方法
        public Student(String name,int age) {
            this.name=name;
            this.age=age;
        }
 //3.定义set,get成员方法       
		public void setAge(int age) {this.age = age;}
		public void setName(String name) {this.name = name;}
		public int getAge() {return age;}
		public String getName() {return name;}

//4.定义一个show方法
        public  void show() {
            System.out.println(name+","+age);
	}
}

4. 常用API概述

4.1 API概述

1.什么是API
API (Application Programming Interface) :应用程序编程接口

2.java中的API
指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用。

Tip:
java中的内置类在底层的实现里已经定义好了他的构造方法和成员方法,所以在创建了内置类的对象后,直接在new 类名();的括号内填入相应的数据即可,如果要调用相应功能成员方法,直接用创建好的对象进行调用即可。

3.如何使用API帮助文档
a.打开帮助文档
b.找到索引选项卡中的输入框
c.在输入框中输入"类名"
d.看类在哪个包下
e.看类的描述
f.看构造方法
g.看成员方法

注意
调用方法的时候,如果方法有明确的返回值,我们用变量接收,可以手动完成,也可以用Ctrl+Alt+V完成

Tip:Scanner类,可以用来键盘录入基本数据类型和字符串

4.2 String类

1.String类概述
String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象。
Tip:String 类在 java.lang 包下,所以使用的时候不需要导包!

2.String类的特点
(1)字符串不可变,它们的值在创建后不能被更改
(2)虽然 String 的值是不可变的,但是它们可以被共享
(3)字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )

3.String类的构造方法
常用的构造方法 (方法名 ------说明)

1.public String()   			创建一个空白字符串对象,不含有任何内容 
2.public String(char[] chs)     根据字符数组的内容,来创建字符串对象 
3.public String(byte[] bys)    根据字节数组的内容,来创建字符串对象 
4.String s = “abc”;       (不是构造方法)直接赋值的方式创建字符串对象,内容就是abc 

String类三种构造方法演示:
public class StringDemo01 {
    public static void main(String[] args) {
//1.public String()           创建一个空白字符串对象,不含有任何内容
       				 //创建对象
               		String s1=new String();
                	System.out.println("s1:"+s1); //String类输出的对象,是String的内容,而不是对象地址              
//2.public String(char[] chs) 根据字符数组的内容,来创建字符串对象
                    //先定义一个char类型的数组
                    char chs[]={'a','b','c'};
                	//创建对象
                    String s2=new String(chs) ;
                    System.out.println("s2:"+s2);
//3.public String(byte[] bys) 根据字节数组的内容,来创建字符串对象
                    //先定义一个byte类型的数组
                    byte  byt[]={97,98,99};
                    //创建对象
                    String s3=new String(byt);
                    System.out.println("s3:"+s3);//字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )
//4.String s = “abc”;   直接赋值的方式创建字符串对象,内容就是abc
                    String s4="abc";
                    System.out.println("s4:"+s4);

    }
}

4.创建字符串对象两种方式的区别

(1)通过构造方法创建
通过 new 创建的字符串对象,每一次 new 都会申请一个新的内存空间,虽然内容相同,但是地址值不同

(2)直接赋值方式创建
以“ ”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护

5.字符串的比较

(1)==号的作用
比较基本数据类型:比较的是具体的值

比较引用数据类型:比较的是对象地址值

(2)equals方法的作用
比较的是字符串的内容(字符排序,英文大小写)是否相同,是通过一个方法来实现的,这个方法叫equals()

6.String常用方法

1.public boolean equals(Object anObject)  	比较字符串的内容,严格区分大小写(用户名和密码) 
2.public char charAt(int index)   			返回指定索引处的 char
3.public int length()   					返回此字符串的长度

4.3 StringBuilder类

1.StringBuilder类概述
StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的

Tip:如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,即耗时,又浪费内存空间,而这种操作又不可避免,所以引入----StringBuilder类

2.StringBuilder类和String类的区别
String类: 内容是不可变

StringBuilder类:内容是可变

3.StringBuilder类的构造方法

1.public StringBuilder()   //创建一个空白可变字符串对象,不含有任何内容 
2.public StringBuilder(String str)   //根据字符串的内容,来创建可变字符串对象 

4.StringBuilder类添加和反转方法

1.添加方法
public StringBuilder append(任意类型)   //添加数据,并返回对象本身
//注意:参数为任意类型 
范例:
public class StringBuilderDemo{
	public static void main(){
	
	//创建StringBuilder类的对象
	StringBuilder sb=new StringBuilder();
	//添加数据,并返回对象本身
	StringBuilder sb2=sb.append("hello");
	System.out.println("sb:"+sb);   //输出结果为:hello
	System.out.println("sb2:"+sb2);	//输出结果为:hello
 	System.out.println(sb==sb2);	//输出结果为:ture,(地址值相同说明sb和sb2是同一个对象)
 	
 	//链式编程:因为StringBuilder类调用append()方法,返回的是对象本身,而对象本身也是对象,所以也可以调用方法
 	//示例:
 	sb.append("hello").append("world").append(100)
 	
	}
}
2.反转方法
public StringBuilder reverse()    返回相反的字符序列

5.StringBuilder和String相互转换

Tip:StringBuilder中有两个非常好用的方法append()和reverse(),为了能使用这两个方法就需要用到相互转换

(1)StringBuilder转换为String

public String toString()   通过 toString() 就可以实现把StringBuilder 转换为 String  
范例:
public class StringBuilderDemo{
	public static void main(){
	
	//创建StringBuilder类的对象
	StringBuilder sb=new StringBuilder();
	//把StringBuilder转换为String
	String s=sb.toString();	
	System.out.println(s);	//输出结果即为 String类型
	
	}
}

(2)String转换为StringBuilder

public StringBuilder(String s)   ==通过构造方法==就可以实现把String转换为StringBuilder 
范例:
public class StringBuilderDemo{
	public static void main(){
	
	//先定义一个String类型的变量
	String s="hello"
	//使用StringBuilder的构造方法把String转换为StringBuilder
 	StringBuilder sb=new StringBuilder(s) 
 	System.out.println(sb);	//输出结果即为 StringBuilder类型
	
	}
}

4.4 ArrayList类

1.集合类的特点
提供一种存储空间可变的存储模型,存储的数据容量可以发生改变

2.ArrayList集合的特点
底层是数组实现的,长度可以变化

3.泛型< E >的使用
< E >是用来约束集合中存储元素的特殊数据类型,在出现E的地方我们使用引用数据类型替换即可

举例:ArrayList< String> , ArrayList< Student>

4.ArrayList类常用方法

(1)构造方法

public ArrayList(){ }      				//创建一个空的集合对象 

(2)成员方法

1.public boolean remove(Object o)     	//删除指定的元素,返回删除是否成功 
2.public E remove(int index)         	//删除指定索引处的元素,返回被删除的元素 
3.public E set(int index,E element)  	//修改指定索引处的元素,返回被修改的元素 
4.public E get(int index)           	//返回指定索引处的元素 
5.public int size() 					//返回集合中的元素的个数 
6.public boolean add(E e) 		   		//将指定的元素追加到此集合的末尾 
7.public void add(int index,E element)  //在此集合中的指定位置插入指定的元素

4.5 Math类

4.5.1 Math类概述

Math 包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。

4.5.2 Math中方法的调用方式

Math 类中无构造方法,但内部的方法和变量都是静态的(被static修饰),可以通过类名进行调用

Tip:当一个类没有构造方法时,就不能创建对象,调用类的成员。但是当这个类是被static修饰的,就直接可以通过类名调用成员。

4.5.3 Math类的常用方法

public static int abs(int a)   //返回参数的绝对值
public static double ceil(double a) //返回大于或等于参数的最小double值,等于一个整数
public static double floor(double a)  //返回小于或等于参数的最大double值,等于一个整数
public static int round(float a)   //按照四舍五入返回最接近参数的int值
public static int max(int a,int b)  //返回两个int值中的较大值
public static int min(int a,int b)    //返回两个int值中的较小值
public static double pow(double a,double b)   //返回a的b次幂的值
public static double random()    //返回值为double的正值[0.0,1.0)

4.6 System类

System 类的常用方法

public static void exit(int status) 	//终止当前运行的 Java 虚拟机,非零表示异常终止
public static long currentTimeMillis()  //返回当前时间(以毫秒为单位)

4.7 Object类

4.7.1 Object 类概述

Object是类层次结构的根,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类

换句话说,该类所具备的方法,所有类都会有一份

Tip:对数据的操作的本质是在内存给他分配了空间才可以进行数据的处理。null的意义就是空的。也就是没有分配任何的空间。new之后,内存会分配一个地址对你new的对象。也就是这个对象指向一个地址。然后对其进行操作。再具体的就交给计算机了。对象赋值,就是栈中的地址指向堆中的数据改变。一般new的时候会给堆中默认值。

4.7.2 Object 类的toString方法

(1)查看方法源码的方式
选中方法,按下 Ctrl + B

(2)toString方法的作用
返回对象的字符串表示形式,结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖重写)此方法

(3)如何自动重写toString方法
Alt + Insert 选择toString(以良好的格式,更方便的展示对象中的属性值)

//学生类
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
	
	//自动重写toString方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
//测试类
public class ObjectDemo {
    public static void main(String[] args) {
        Student s=new Student("林青霞",30);

        System.out.println(s);//com.itheima_01.Student@7c30a502 此处是为了研究对象的输出结果代表的含义
        System.out.println(s.toString());//输出结果为com.itheima_01.Student@7c30a502,说明学生对象底层调用了toString()方法
       
       		1.选中println(),Ctrl+B追踪方法源代码
        /*
        public void println(Object x) {		//x=s
            String s = String.valueOf(x);
            synchronized (this) {
                print(s);
                newLine();
            }
        }
        */
        
			2.选中valueOf(),Ctrl+B追踪方法源代码
       /*
       public static String valueOf(Object obj) {	//obj=x
            return (obj == null) ? "null" : obj.toString();		//s是Student类的对象,而Student类都继承自Object类,所以可以调用Object类中的toString()方法
        }
       */
       
			3.选中toString(),Ctrl+B追踪方法源代码
        /*
        public String toString() {
           return getClass().getName() + "@" +Integer.toHexString(hashCode()); 		
        }   // getClass().getName()  类的全路径名(带包名的类名)
        */
    }

}

4.7.3 Object类的equals方法

(1)equals 方法的作用
用于对象之间的比较,返回 true和false的结果

举例: 
s1.equals(s2);

(2)重写 equals方法的场景
不希望比较对象的地址值,想要结合对象属性进行比较的时候。

(3)重写 equals方法的方式
1 . alt + insert 选择equals() and hashCode(),IntelliJ Default,一路next,finish即可

//学生类
public class Student {
    private String name;
    private int age;

    public Student() {}
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //重写equals方法
    @Override    //三元运算符比较的
    public boolean equals(Object o) {
        //this -----s1,方法被谁调用谁就是this
        //o----------s2,这里是多态向上转型:Object o=new Student();

        //比较两个对象地址是否相同,如果相同,返回true
        if (this == o) return true;

        //判断参数是否为null  ,如果是返回false
        //判断两个对象是否来自于同一个类,如果是返回false
        if (o == null || getClass() != o.getClass()) return false;

        //向下转型
        Student student = (Student) o;  //student=s2;(重点理解)

        //判断年龄是否相同,没有修饰的age,name前面隐含this
        if (age != student.age) return false;

        //判断姓名是否为空值,姓名是否相同,此处的equals方法是String类里的,因此它比较的是name字符串的内容是否相同
        Tip:此处的name前面是有this修饰的
        return name != null ? name.equals(student.name) : student.name == null;
    }
}
 
public class ObjectDemo {
    public static void main(String[] args) {
    
        Student s1=new Student("林青霞",30);
        Student s2=new Student("林青霞",30);

        //要求比较两个类的对象的内容是否相等
        System.out.println(s1==s2);   //这是在比较两个对象的地址
        System.out.println(s1.equals(s2)); 	//输出结果为flase,说明还是在比较对象的地址,所以需要重写equals方法
        
        查看equals方法的源码:
        /*
        public boolean equals(Object obj) {
        //this------s1   谁调用方法,谁就是this
            //obj-------s2   参数要求为Object类,这里传入的是s2,
                            //这里用到了多态向上转型:Object obj=new Student();
            return (this == obj); //可以看出equals方法还是在比较两个对象的地址值,所以得重写equals方法
        }
        */
    }
}

4.8 Arrays类

4.8.1 冒泡排序

一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序。如果有 n个数据进行排序,总共需要比较n-1次,每一次比较完毕,下一次的比较就会少一个数据参与

实例:
public class ArrayDemo {
    public static void main(String[] args) {
        //定义一个数组:
        int arr[]={21,65,13,24,88,66};

        //排序前
        System.out.println("排序前:"+arrToString(arr));
		
		for循环排序的操作在main方法里完成
        //将数组类的元素进行冒泡排序,并遍历
        for (int i = 0; i < arr.length-1; i++) {  //arr.length-1代表冒泡排序的总次数,即元素个数-1
            for (int x = 0; x < arr.length-1-i; x++) {//-1是防止索引越界,由arr[x+1]中的x+1造成
                if (arr[x]>arr[x+1]) {       //-i是因为每次排序完成后,下次需要排序的元素个数,有累计效果
                    int temp=arr[x];         //即第一次需要排序的元素个数-0,第二次-1,第三次-2.....最后一次-i
                    arr[x]=arr[x+1];
                    arr[x+1]=temp;
                }
            }
        }
        System.out.println("排序后:"+arrToString(arr));   //输出的遍历结果放在循环外面
    }
    //定义一个方法把int类型数组转化为String类型的数组
    public  static  String   arrToString(int arr[]) {
        //1.先创建StringBuilder类对象,为了方便使用 StringBuilder类的添加方法
        StringBuilder sb=new StringBuilder();

        //2.遍历数组
        sb.append("[");
        for (int x = 0; x < arr.length; x++) {
            if (x == arr.length-1) {
                sb.append(arr[x]);
            }else {
                sb.append(arr[x]).append(",");
            }
        }
        sb.append("]");
        //3.把StringBuilder类转换为String类
            String s = sb.toString();
            return s;
    }
}

4.8.2 Arrays 的常用方法

public static String toString(int[] a)   //返回指定数组的内容的字符串表示形式
public static void sort(int[] a)    //按照数字顺序排列指定的数组
示例:
import java.util.Arrays;
public class ArrayDemo {
    public static void main(){
        int arr[]={13,24,8,75,12,10};

        //把int类型的数组转为字符串数组
        Arrays.toString(arr);

        //对字符串数组冒泡排序
        Arrays.sort(arr);
        System.out.println(arr);
    }
}

4.8.3 工具类设计思想

(1)构造方法用 private 修饰-------防止外界创建对象

(2)成员用 public static 修饰-------为了使用类名调用成员方法

4.9 包装类

4.9.1 基本类型包装类

(1)基本类型包装类的作用
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据

(2)常用的操作
用于基本数据类型与字符串之间的转换

(3)基本类型对应的包装类
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210326101339931.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0wxNTEyMjY5ODkwMg==,size_16,color_FFFFFF,t_70

4.9.2 Integer类

(1)Integer 类概述
包装一个对象中的原始类型 int 的值

(2)Integer 类构造方法

public Integer(int value)       根据 int值创建 Integer对象(过时)
public Integer(String s)    	根据 String值创建 Integer对象(过时)
public static Integer valueOf(int i)       返回表示指定的int值的Integer 实例
public static Integer valueOf(String s)     返回一个保存指定值的Integer对象 String
举例:
public class IntegerDemo {

    public static void main(String[] args) {

        /*
        //1.public  class Integer(int value){ }
        Integer i=new Integer(100); //划横线,该构造方法过时

        //2.public  class Integer(String str){ }
        Integer i2=new Integer("100");  //划横线,该构造方法过时
        System.out.println(i2);

        Integer i3=new Integer("abc");  //报错 NumberFormatException,只能接收数字类型的数据
        System.out.println(i3);
        */


        //静态方法获取对象,不用再创建方法,直接用类名调用方法即可
        //1.public static Integer valueOf(int i)       返回表示指定的int值的Integer 实例
            System.out.println(Integer.valueOf(100));

        //2.public static Integer valueOf(String s)     返回一个保存指定值的Integer对象 String
            System.out.println(Integer.valueOf("120"));
    }
}

4.9.3 int和String类型的相互转换

int 转换为String

方式一:直接在数字后加一个空字符串

方式二:通过 String类静态方法valueOf(推荐

String 转换为int

方式一:先将字符串数字转成 Integer,再调用valueOf()方法
方式二:通过 Integer静态方法parseInt()进行转换(推荐

示例:
public class IntegerDemo {

    public static void main(String[] args) {
        //定义一个int类型的数据
        int i=100;

        //int-------->String
        //方法一:int类型的数据与空字符串拼接
               String s=i+"";           //空字符串和一个数据进行拼接,返回的是数据本身且为String类型(此操作过程不改变i的属性)
               System.out.println(s);
        //方法二:调用 String方法
                System.out.println(String.valueOf(i));
                System.out.println("--------------");


        //定义一个String类型的数据
                String str="119";
        //String-------->int

        //方法一:String---->Integer---->int
                //1.String---->Integer
                Integer ss = Integer.valueOf(str);
                //2.Integer---->int
                int x = ss.intValue();
                System.out.println(x);
        //方法二:public static int parseInt(String s)
                Integer.parseInt(str);
                System.out.println(Integer.parseInt(str));
    }
}
/*案例需求:
        有一个字符串:“91 27 46 38 50”,请写程序实现最终输出结果是:“27 38 46 50 91” */
//思路:
//1.定义一个字符串
//2.把字符串的数字数据提取出来,放到一个int数组中
//3.对int数组进行冒泡排序
//4.把排好序的int数组里面的元素进行字符串拼接
import java.util.Arrays;
public class IntegerDemo {
    public static void main(String[] args) {
        //1.定义一个字符串
                String s="91 27 6 38 50";

            //把该字符串转换成一个字符串数组
                String strArray[]=s.split(" "); 
//split方法是用来识别字符串内每个数据之间是用什么符号隔开的,并进行切割,得到字符串里的每一个数据                
/*
                for (int x = 0; x <strArray.length ; x++) {
                    System.out.print(strArray[x]);
                }

 */

       //2.把字符串的数字数据提取出来,放到一个int数组中
            //定义一个int数组,数组的长度要和字符串数组相同
                int intArray[]  = new int[strArray.length]; //定义后两个数组的长度相同

            //把字符串数组类的元素,赋值到int数组类,遍历
                for (int y = 0; y <intArray.length ; y++) {
                    intArray[y]=Integer.parseInt(strArray[y]);  //数组长度相同,所以x和y相同,两个索引可以填同一个
                }

        //3.对int数组排序
                Arrays.sort(intArray);
        //4.对排序后的int数组元素进行拼接
                //这里使用StringBuilder的方法进行拼接
                StringBuilder sb=new StringBuilder();

                for (int y = 0; y <intArray.length; y++) {
                    if (y == intArray.length-1) {
                        sb.append(intArray[y]);
                    }else{
                        sb.append(intArray[y]).append(" ");
                    }
                }

                //把StringBuilder转换为String,最后输出结果
                String result = sb.toString();
                System.out.println(result);
    }
}

4.9.4 自动拆箱和自动装箱

自动装箱
把基本数据类型转换为对应的包装类类型

自动拆箱
把包装类类型转换为对应的基本数据类型

示例:
public class IntegerDemo {
    public static void main(String[] args) {

        //装箱:把基本数据类型转换为对应的包装类类型
            Integer i = Integer.valueOf(100);
        //自动装箱:
            Integer i2=100;


        //拆箱:把包装类类型转换为对应的基本数据类型
            //i2+=200;
            //i2=i2+200;
            //i2=i2.intValue()+200;    //i2.intValue()这个动作就是拆箱
        //自动拆箱:
            i2+=200;

            //注意:
              Integer i3=null;
                //i3+=200;   //NullPointerException,对象不能为null,否则不能调方法
            //先判断对象是否为空值
            if(i3!=null){
                System.out.println(i3+=200);
            }
    }
}

4.10 Date类

(1)Date 类概述

Date 代表了一个特定的时间,精确到毫秒

(2)Date 类构造方法

public Date()       分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
输出Date对象,为当前时间日期,说明被改写了toString方法
public Date(long date) 分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
示例:
import java.util.Date;
public class DateDemo {
    public static void main(String[] args) {
        //构造方法:
        //1.public Date()  分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
        Date d=new Date();
        System.out.println(d);  //输出Date对象,为当前时间日期,说明被改写了toString方法

        //2.public Date(long date)  分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
        long s=1000*60*60;  //一小时
        Date d2=new Date(s);
        System.out.println(d2); //输出结果应该为 1970年 1月1日1时0分0秒(误差原因是时区不同)
    }
}

(3)Date 类常用方法

public long getTime()          获取的是日期对象从19701100:00:00到现在的毫秒值
public void setTime(long time)        设置时间,给的是毫秒值
import java.util.Date;
public class DateDemo {
    public static void main(String[] args) {
        Date date=new Date();
        //public long getTime()          获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值
        System.out.println(date.getTime()*1.0/1000/60/60/24/365+"年");

        //public void setTime(long time)        设置时间,给的是毫秒值
         //long time=1000*60*60;
        long time=System.currentTimeMillis();
        System.out.println(date);
    }
}

4.11 SimpleDateFormat类

(1)SimpleDateFormat 类概述
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
Tip:我们重点学习日期格式化和解析

(2)SimpleDateFormat 类构造方法


public SimpleDateFormat() 		构造一个SimpleDateFormat,使用默认模式和日期格式
public SimpleDateFormat(String pattern)   	构造一个SimpleDateFormat使用给定的模式和默认的日期格式

(3)SimpleDateFormat 类的常用方法

格式化 (从Date到String)

public final String format(Date date)   将日期格式化成指定日期/时间字符串

解析 (从String到Date)

public Date parse(String source)   从给定字符串的开始解析文本以生成日期(date默认模式)
示例:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo {
    public static void main(String[] args) throws ParseException {
        //格式化:从Date到String

        Date date=new Date();
        //1.public SimpleDateFormat() 		构造一个SimpleDateFormat,使用默认模式和日期格式
        //SimpleDateFormat sdf=new SimpleDateFormat();
        //System.out.println(sdf.format(date));

        //2.public SimpleDateFormat(String pattern)   	构造一个SimpleDateFormat使用给定的模式和默认的日期格式
         SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
            //public final String format(Date date)   将日期格式化成日期/时间字符串
            String s = sdf.format(date);
            System.out.println(s);

        //解析:从String到Date
            //定义一个字符串日期
             String str="2080年10月01日 10时11分12秒";
             SimpleDateFormat sdf2=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");//此处给出的模式必须要与字符串模式相同
             Date ss = sdf2.parse(str);  //此处抛去异常
             System.out.println(ss);


    }
}
/*案例需求
定义一个日期工具类(DateUtils),包含两个方法:把日期转换为指定格式的字符串;把字符串解析为指定格式
的日期,然后定义一个测试类(DateDemo),测试日期工具类的方法*/
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtils {
//一般构造方法私有化,成员方法静态化
    private DateUtils(){}

    //1.格式化
    public static String dateToString(Date date,String format) {//参数有两个: 1.Date  2.字符串模式
        //创建日期类对象
        SimpleDateFormat sdf=new SimpleDateFormat(format);
        String s = sdf.format(date);
        return  s;
    }

    //2.解析
    public static Date stringToDate(String str,String format) throws ParseException {
        SimpleDateFormat sdf=new SimpleDateFormat(format);
        Date ss = sdf.parse(str);
        return ss;
    }
}
import java.text.ParseException;
import java.util.Date;
public class DateUtilsDemo {
    public static void main(String[] args) throws ParseException {

        Date d=new Date();
        //静态方法直接用类名调用
        String s = DateUtils.dateToString(d, "yyyy年MM月dd日 HH:mm:ss");
        System.out.println(s);
        
        Date ss = DateUtils.stringToDate("2024年10月11日 08:09:10", "yyyy年MM月dd日 HH:mm:ss");
        System.out.println(ss);
    }
}

4.12 Calendar类

(1)Calendar 类概述
Calendar 为特定瞬间与一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法

Calendar 提供了一个类方法 getInstance 用于获取这种类型的一般有用的对象,该方法返回一个Calendar 对象。

其日历字段已使用当前日期和时间初始化:

Calendar rightNow = Calendar.getInstance();

(2)Calendar 类常用方法

public int get(int field)          返回给定日历字段的值
 public abstract void add(int field, int amount)   根据日历的规则,将指定的时间量添加或减去给定的日历字段
 public final void set(int year,int month,int date)设置当前日历的年月日
import java.util.Calendar;
public class CalendarDemo {
    public static void main(String[] args) {
        //创建Calendar抽象类对象
        //方法的返回值类型为抽象类 ,(多态)其实是需要该抽象类的子类对象
        Calendar c = Calendar.getInstance();
        System.out.println(c);

        //1.通过get方法获取Calendar日历中的字段
//        int y = c.get(Calendar.YEAR);
//        int m = c.get(Calendar.MONTH) + 1;
//        int d = c.get(Calendar.DAY_OF_MONTH);
//        System.out.println(y + "年" + m + "月" + d + "日");

        //2.public abstract void add(int field, int amount)   根据日历的规则,将指定的时间量添加或减去给定的日历字段

        //需求:三年前的两天前
//        c.add(Calendar.YEAR,-3);
//        c.add(Calendar.DATE,-2);
//
//        int y = c.get(Calendar.YEAR);
//        int m = c.get(Calendar.MONTH) + 1;
//        int d = c.get(Calendar.DAY_OF_MONTH);
//        System.out.println(y + "年" + m + "月" + d + "日");

        //3.public final void set(int year,int month,int date)设置当前日历的年月日
            c.set(2666,11,12);

            int y = c.get(Calendar.YEAR);
            int m = c.get(Calendar.MONTH) + 1;
            int d = c.get(Calendar.DAY_OF_MONTH);
            System.out.println(y + "年" + m + "月" + d + "日");
    }
}
/*案例:
任意一年的2月有多少天?*/
/*思路:
2月份的天数,就是3月1号之前的一天*/
import java.util.Calendar;
import java.util.Scanner;
public class CalendarDemo {
    public static void main(String[] args) {

        Scanner sc=new Scanner(System.in);
        System.out.println("请输入年份");
        int year=sc.nextInt();

        Calendar c=Calendar.getInstance();
        c.set(year,2,1); //要修改为3月,就得输入2,因为月份是从0开始的

        c.add(Calendar.DAY_OF_MONTH,-1);

        int y = c.get(Calendar.YEAR);
        int m = c.get(Calendar.MONTH);
        int d = c.get(Calendar.DAY_OF_MONTH);

        System.out.println(y+"年的2月共有: "+d+ "天");
    }
}

5. 继承

5.1 继承的实现

5.1.1 继承的概念

继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法。

5.2.2 实现继承的格式

继承通过extends实现
格式:class 子类 extends 父类 { }

举例:
	  class Dog extends Animal { } 

5.2 继承的好处和弊端

5.2.1 继承好处

提高了代码的复用性(多个类相同的成员可以放到同一个类中)

提高了代码的维护性(如果方法的代码需要修改,修改一处即可)

2.继承弊端
继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性

5.3 继承中的成员访问特点

5.3.1 继承中变量的访问特点 (重点理解)

子类方法中访问一个变量,采用的是就近原则

(1)子类局部范围(即成员方法内)找

(2)子类成员范围找

(3)父类成员范围找

(4)如果都没有就报错(不考虑父亲的父亲…)

5.3.2 super关键字

(1)this&super关键字

this:代表本类对象的引用

super:代表父类存储空间的标识(可以理解为父类对象引用)

(2)this和super的使用分别

this.成员变量/成员方法 ------------访问本类成员变量或者本类成员方法

super.成员变量/成员方法 ----------访问父类成员变量或者本类成员方法

(3)构造方法:

this(…); ---------------访问本类构造方法

super(…) ; ------------访问父类构造方法

5.3.3 继承中构造方法的访问特点

子类中所有的构造方法都会默认访问父类中的无参构造方法

原因:子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,

//每一个子类构造方法的第一条语句默认都是:super() 
class Zi extends Fu{
	//Zi类无参构造方法
	class Zi(){
		super(); //第一条语句默认都是super(),系统隐藏了它的显示
	}
}

问题
如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?

Tip: 子类构造方法中的,第一条语句默认都是super(),即先要访问父类中的无参构造方法,而父类中没有定义无参构造方法,这时系统就会报错。

解决方法

(1)通过使用super关键字去显示的调用父类的带参构造方法

class Zi extends Fu{
	//Zi类无参构造方法
	class Zi(){
	   //super(); 
		super(age:20); 
	}
	
	//Zi类带参构造方法
	class Zi(int age){
	 	//super();
		super(age:20); 
	}
}

(2)在父类中自己提供一个无参构造方法

推荐方案:在父类中自己给出无参构造方法

5.3.4 继承中成员方法的访问特点

通过子类对象访问一个方法:
(1)子类成员范围找

(2)父类成员范围找

(3)如果都没有就报错(不考虑父亲的父亲…)

5.3.5 super内存图

对象在堆内存中,会单独存在一块super区域,用来存放父类的数据

5.3.6 方法重写

(1)方法重写概念
子类出现了和父类中一模一样的方法声明(方法名一样,参数列表也必须一样

(2)方法重写的应用场景
a. 通过使用super关键字去显示的调用父类的带参构造方法

b.在父类中自己提供一个无参构造方法当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容

(3)Override注解
用来检测当前的方法,是否是重写的方法,起到校验的作用

5.3.7 方法重写的注意事项

(1)私有方法不能被重写(父类私有成员,子类是不能继承的)

(2)子类方法访问权限不能更低(public >protect> 默认 > private)

5.3.8 Java中继承的注意事项

(1)Java中的类只支持单继承,不支持多继承

//错误范例:
class A extends B, C { }

(2)Java中类支持多层继承

C继承了B,B继承了A ( C—>B—>A)

6. 修饰符

6.1 package(包)

6.1.1 包的概念

包就是文件夹,用来管理类文件的

6.1.2 包的定义格式

package 包名; (多级包用.分开)

例如:
package com.heima.demo; 
6.1.3 带包编译&带包运行

带包编译:javac –d . 类名.java (d后面加空格,再加点)
例如:javac -d . com.heima.demo.HelloWorld.java

带包运行:java 包名+类名
例如:java com.heima.demo.HelloWorld

6.2 import(导包)

6.2.1 导包的意义

使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了,为了简化带包的操作,Java就提供了导包的功能

6.2.2 导包的格式

格式:import 包名;

范例:
import java.util.Scanner; 

6.3 权限修饰符

Tip:

权限由大到小:public>protect>默认>private
在这里插入图片描述

6.4 状态修饰符

6.4.1 final概述

(1)final关键字的作用
final代表最终的意思,可以修饰成员方法,成员变量,类

(2)final修饰类、方法、变量的效果

修饰:该类不能被继承(不能有子类,但是可以有父类)

修饰方法:该方法不能被重写

修饰成员变量:表明该成员变量是一个常量,不能被再次赋值

final修饰局部变量:

a.修饰基本数据类型变量

指的是基本类型的数据值不能发生改变

b.修饰引用数据类型变量

指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的

范例:
public class StringBuilderDemo{
	public static void main(){
	final int num=10;
	num=20;  //系统报错,说明:被final修饰的基本类型的数据值不能发生改变

	//用final修饰的学生类
	final Student s=new Student();
   	s.age=100;				//Student类中的age值为20
 	System.out.println(s.age);	//输出的age的值为100,说明地址里面的内容是可以发生改变的
 	
 	//验证s的地址值不能被改变
 	s=new Student();  //系统报错,说明引用类型的地址值不能发生改变
	
	}
}
6.4.2 static概述

(1)static的概念
static关键字是静态的意思,可以修饰成员方法,成员变量

(2)static修饰的特点
a.被类的所有对象共享,这也是我们判断是否使用静态关键字的条件

b.可以通过类名调用,当然也可以通过对象名调用,推荐使用类名调用

//学生类
public class Student{

	public String name;					//姓名
	public int age;						//年龄
	public static String university;	//大学	

	public void show(){
		System.out.println(name+","+age+","+university);
	}
	
}
//学生测试类
public class StudentDemo{
	public static void main(){
	
	/*
		Student s=new Student();
		s.name="小李";
		s.age=  20;
		s.name="清华大学";
		s.show();
	
		Student s2=new Student();
		s2.name="小王";
		s2.age=  18;
		s2.name="清华大学";
		s2.show();
		//由于创建的两个对象s 和 s2,的成员变量“大学”是相同的,所以能对学生类中的成员变量university用static修饰,并可以直接用类名进行调用。
		*/
			Student.name="清华大学";	//用类名进行调用
			
			Student s=new Student();
			s.name="小李";
			s.age=  20;
			s.show();
			
			Student s2=new Student();
			s2.name="小王";
			s2.age=  18;
			s2.show();

	}
}
6.4.3 static访问特点

(1)非静态的成员方法

能访问静态的成员变量
能访问非静态的成员变量
能访问静态的成员方法
能访问非静态的成员方法
总结成一句话就是: 非静态成员方法能访所有成员

(2)静态的成员方法
能访问静态的成员变量
能访问静态的成员方法

总结成一句话就是: 静态成员方法只能访问静态成员

//学生类
public class Student{

	//非静态成员变量
	public String name="小李";	
	
	//静态成员变量				
	public static String university="清华大学";

	//非静态成员方法
	public void show1(){
	}
	//非静态成员方法
	public void show2(){
			System.out.println(name);
			System.out.println(university);
			show2();
			show3();
			
	}
	//静态成员方法
	public static void show3(){
			System.out.println(name);		//报错,name是非静态成员变量
			System.out.println(university);  
			show1();						//报错,show1()是非静态成员方法
			show4();
	}
	//静态成员方法
	public static void show4(){
	}
	
}

7.多态

7.1 多态的概述

(1)什么是多态
同一个对象,在不同时刻表现出来的不同形态

(2)多态的前提
要有继承或实现关系

要有方法的重写

要有父类引用指向子类对象(子类对象是研究的对象)

7.2.多态中的成员访问特点

(1)成员变量
编译看父类,运行看父类

(2)成员方法
编译看父类,运行看子类

Tip:为什么成员变量和成员方法的访问不一样?
因为成员方法有重写,而成员变量没有

//动物类
public class Animal{
	public int age=40;
	
	public void eat(){
	System.out.println("动物吃东西");
	}
}
//猫类
public class Cat extends Animal {
	public int age=20;
	//方法重写
	public void eat(){
	System.out.println("猫吃鱼");
	}
	//猫类特有方法
	public void shou(){
	System.out.println("猫抓老鼠");
	}
}
//测试类
public class AnimalDemo{
	public static void main(){
	//父类引用指向子类对象
	Animal a=new Cat();
	
	System.out.println(s.age); //输出结果为Animal类中的age值40,编译和执行都看Animal类
	s.eat(); 					//编译看Animal类 ,运行为Cat中的eat方法
	s.show(); 					  //系统报错,编译看Animal类 ,Animal类中没有该方法,即不能访问子类的特有成员
	}	
}

7.3 多态的好处和弊端 (重点理解

好处
提高程序的扩展性。定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作

弊端
不能使用子类的特有成员

//Animal类
public class Animal{
	public void eat(){
		System.out.println("动物吃东西");
	}
}
//Cat类
public class Cat extends Animal {
	//方法重写
	@Override
	public void eat(){
		System.out.println("猫吃鱼");
	}
}
//Dog类
public class Dog extends Animal {
	//方法重写
	@Override
	public void eat(){
		System.out.println("狗吃屎");
	}
}
//Animal操作类
public class AnimalOperator{
	/*
		//该类中的两个方法构成了方法重载,具体访问哪个方法看的是参数列表
		public void Operator(Cat c ){	// Cat c=new Cat();
			c.eat();
	}
		public void Operator(Dog d ){	// Dog d=new Dog();
			c.eat();
	}
	*/
	//直接把该方法参数设置成Animal类型(多态的形式)
	public void Operator(Animal a ){ 
	  	//Animal a=new Cat();
	  	//Animal a=new Dog();
			a.eat();
}
//Animal测试类
public class AnimalDemo{
	public static void main(){
	
	//创建Animal操作类对象,调用Opertor方法
	AnimalOperator ao=new AnimalOperator();
	Cat c=new Cat();	//c是Cat类的对象
	ao.Operator(c); 	//Operator方法内的参数值类型为Cat,Dog类,参数值为c,d,这时就需要先创建一个Cat或者Dog类对象,然后把该对象传给Operator方法
	
	Dog d=new Dog();	
	ao.Operator(d);
	}	
}

7.4 多态中的转型

向上转型
父类引用指向子类对象

//格式:
父类型 对象名 =new  子类型; 
//范例:
Animal a =new  Cat; 

格式:子类型 对象名 = (子类型)父类引用;

向下转型
父类引用转为子类对象 (其目的就是为了能在多态的形式下,直接访问子类特有的成员

//格式:
子类型 对象名 = (子类型)父类引用; 
//范例:
Cat c =(Cat)a;
//Animal类
public class Animal{
	public void eat(){
		System.out.println("动物吃东西");
	}
}
//Cat类
public class Cat extends Animal {
	//方法重写
	@Override
	public void eat(){
		System.out.println("猫吃鱼");
	}
	//猫类特有成员方法
	public void play(){
		System.out.println("猫会抓老鼠");
	}
}
//Animal测试类
public class AnimalDemo{
	public static void main(){
	//多态
	Animal a=new Cat();
	a.eat();
	//为了能访问子类特有的成员方法
	Cat c=(Cat)a;
	c.eat();
	c.play();
	}	
}

8. 抽象类

8.1 抽象类的概述

在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

8.2 抽象类的特点

(1)抽象类和抽象方法都被abstract关键字修饰

public abstract class 类名{} 
public abstract void eat(); 

(2)抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类

(3)抽象类不能创建对象(Animal a=new Animal(); 系统报错)

(4)抽象类(抽象父类)的子类,要么重写抽象类中的所有抽象方法 ,要么是子类本身就是抽象类

tip:抽象类如何创建对象(即实例化)
参照多态的方式,通过子类对象实例化,这叫抽象类多态

8.2 抽象类的成员特点

成员变量: 既可以是变量,也可以是常量(被 final修饰)

构造方法: 空参构造 ,有参构造(抽象类中的构造方法用于子类访问父类数据的初始化,可以参照多态的形式间接的创建对象)

成员方法: 抽象方法(抽象类中定义抽象方法就是为了限定子类中方法的重写) ,普通方法(提高代码的复用性,通过子类的继承实现)

public abstract class Animal{
	//成员变量,常量
	private int age=20private final String name="李洛克"
	
	//无参,带参构造方法
	public Animal(){} 
	public Animal(int age){
		this.age=age
	} 
	//非抽象方法
	public void show(){
			System.out.println(age);
	} 
	//抽象方法
	public abstract void eat();
}

9. 接口

9.1 接口的概述

接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用,Java中的接口更多的体现在对行为的抽象

9.2 接口的特点

(1)接口用关键字interface修饰

  public interface 接口名{}

(2)类实现接口用implements表示

 public class 类名 implements 接口名 {} 

(3)接口不能创建对象

参照多态的方式,通过实现类对象实例化,这叫接口多态。

Tip:
多态的形式:具体类多态,抽象类多态,接口多态。

多态的前提:有继承或实现关系;有方法重写;有接口引用 指向实现类对象

(4)接口的实现类
要么重写接口中的所有抽象方法
要么是抽象类

9.3 接口的成员特点

(1)成员变量
只能是常量,而且是静态的(不能修改常量值,且可以直接用接口名直接调用)

默认修饰符:public static fifinal (定义成员变量时,前面的修饰符都不用写)

(2)构造方法
没有,因为接口主要是扩展功能的,而没有具体存在

原理:接口中没有构造方法,但是接口实现类中默认有一个无参构造方法

public class InterImpl extends Object implements  Interface  {
	public InterImpl(){
		super(); //此处是引用父超类的构造方法,而父超类提供一个无参构造方法,Object()
	}
}

(3)成员方法
只能是抽象方法

默认修饰符:public abstract (定义抽象方法时,前面的修饰符都不用写)

关于接口中的方法,JDK8和JDK9中有一些新特性

9.4 类和接口的关系

类与类的关系
继承关系,只能单继承,但是可以多层继承

类与接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口

接口与接口的关系
继承关系,可以单继承,也可以多继承

9.5 抽象类和接口的区别

抽象类
变量,常量;有构造方法;有抽象方法,也有非抽象方法

接口
常量;抽象方法

关系区别:
(1)类与类 :继承(单继承 )

(2)类与接口 :实现(单实现,多实现 )

(3)接口与接口 :继承(单继承,多继承 )

(4)设计理念区别

抽象类: 对类抽象,包括属性、行为

接口:对行为抽象,主要是行为

10. 参数传递

10.1 类名作为形参和返回值

(1)作为形参
方法的形参是类名,其实需要的是该类的对象

实际传递的是该对象的地址值

(2)作为返回值
方法的返回值是类名,其实返回的是该类的对象

实际传递的,也是该对象的地址值

//Cat类
public class Cat{
	public void eat(){
		System.out.println("猫吃鱼");
	}
}
//Cat操作类
public class CatOperator{
	//类名作为参数
	public void useCat(Cat c){ //Cat c=new Cat();
		c.eat();
	}
	
	//类名作为返回值
	public Cat getCat(){
		Cat c=new Cat();
		return c;
	}
//测试类
public class CatDemo{
	public static void main(){
	//创建操作类对象,调用Cat类中eat方法
	CatOperator co=new CatOperator();
		Cat c=new Cat();
		co.useCat(c);  //useCat()方法的参数类型为Cat类,所以要先创建Cat类的对象,这里的c相当于new Cat();
	
		Cat c2=co.getCat();	
		c2.eat();
	}
}

10.2 抽象类名作为形参和返回值

(1)作为形参
其实需要的是该抽象类的子类对象

(2)作为返回值
其实返回的是该抽象类的子类对象

//Animal类
public abstract class Animal{
	public abstract void eat();
}
//Cat类
public  class Cat extends Animal{
	@Override
	public void eat(){
		System.out.println("猫吃鱼");
	}
}
//Animal操作类
public class AnimalOperator{
	//抽象类名作为参数
	public void useAnimal(Animal a){ 	//Animal a=new Cat();
		a.eat();
	}
	
	//抽象类名作为返回值
	public Animal getAnimal(){
		Animal a=new Cat();
		return a;
	}
//Animal测试类
public class AnimalDemo{
	public static void main(){
	//创建操作类对象,调用操作类方法
	CatOperator co=new CatOperator();
		Animal a=new Cat();
		co.useAnimal(a); 
	
		Animal a2=co.getAnimal();	
		a2.eat();
	}
}

10.3 接口名作为形参和返回值

(1)作为形参
其实需要的是该接口的实现类对象

(2)作为返回值
其实返回的是该接口的实现类对象

//接口
public interface Jumpping{
	void jump();	//接口中的抽象方法可以省略abstract修饰符
}
//接口实现类
public  class Cat implements Jumpping{
	@Override
	public void eat(){
		System.out.println("猫跳起来了");
	}
}
//接口操作类
public class JumppingOperator{
	//接口名作为参数
	public void useJumpping(Jumpping j){ 	//Jumpping j=new Cat();
		j.jump();
	}
	
	//接口名作为返回值
	public Jumpping getJumpping(){
		Jumpping j=new Cat(); 
		return j;
	}
//接口测试类
public class JumppingDemo{
	public static void main(){
	//创建接口操作类对象,调用接口操作类方法
	JumppingOperator jo=new JumppingOperator();
		Jumpping j=new Cat();
		jo.useJumpping(j); 
	
		Jumpping j2=jo.getJumpping();	//Jumpping j2=new Cat();
		j2.eat();
	}
}

11. 内部类

11.1 内部类的基本使用

11.1.1 内部类概念

在一个类中定义一个类。

举例:在一个类 A的内部定义一个类B,类B就被称为内部类

11.1.2 内部类定义格式

格式 &举例:

格式:    
public class 外部类名{
	 修饰符 class 内部类名{}     	   
    }
举例:
public class Outer {
    public class Inner {
    }
}
11.1.3 内部类的访问特点

内部类可以直接访问外部类的成员,包括私有;

外部类要访问内部类的成员,必须创建对象;

举例:
public class Outer {
	private int age=20;
	
   	 public class Inner {
   	 //内部类可以直接访问外部类
    	pubic void method(){
			System.out.println(age);
		}
    }
    
		//外部内要先创建对象,才能访问内部类成员
		Inner i=new Inner();
			i.method();
}

11.2 成员内部类

成员内部类的定义位置:在类的成员位置

11.2.1 外界创建成员内部类格式

格式:外部类名 .内部类名 对象名 = 外部类对象.内部类对象;

举例:
 Outer.Inner oi = new Outer().new Inner();

11.2.2 成员内部类的推荐使用方案

将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用。

举例:
//内部类
public class Outer {
	private int age=20;
	
   	 public class Inner{
    	pubic void method(){
			System.out.println(age);
		}
    }
    
		//外部类里,定义一个方法,在方法里创建内部类的对象
		public void show(){
			Inner i=new Inner();
				  i.method();
	}
}
//测试类
public class OuterDemo{
	public static void main(){
	/*
	//外界的调用方法
	Outer.Inner oi=new Outer().new Inner();
		oi.method();  //当访问的成员为私有时就会报错
	*/	
	
	(推荐使用)
	//创建外部类的对象,调用外部类的方法
	Outer o=new Outer();
	o.show();
	}
}

11.3 局部内部类

(1)局部内部类定义位置:在方法中定义的类

(2)局部内部类访问方式:

局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用

该类可以直接访问外部类的成员,也可以访问方法内的局部变量

//局部内部类
public class Outer {
	private int age=20;
	
    public void method(){
    
		class  Inner{
		public void show(){
			System.out.println(age);
			}
		}

		//创建局部内部类对象
		Inner i=new Inner();
		i.show();

	}
}
//测试类
public class OuterDemo{
	public static void main(){
	
		//创建外部类的对象,调用外部类的方法
		Outer o=new Outer();
		o.method();
	}
}

11.4 匿名内部类

11.4.1 匿名内部类的前提

存在一个类或者接口,这里的类可以是具体类也可以是抽象类

11.4.2 匿名内部类的格式
格式: 
		new 类名/接口名(){ 
			重写方法(类或者接口中的方法)
		}
举例:
		new Inter(){
    		@Override
    		public void method(){
	}
}
11.4.3 匿名内部类的本质

本质:是一个继承了该类或者实现了该接口的子类匿名对象

11.4.4 匿名内部类的细节

(1)匿名内部类可以通过多态的形式接收

Inter i = new Inter(){
  @Override
    public void method(){  
    }
}

Tip:既然匿名内部类的本质是对象,是对象就有返回值类型,new的是Inter接口,而且重写了Inter接口内的方法,所以整体可以看成Inter的实现类对象,所以就可以用多态的形式赋值给接口

(2)匿名内部类直接调用方法

//接口
interface Inter{
    void show();
}
//内部类
public class Outer{
         public void method(){
              Inter i=new Inter(){
	              @Override
	              void show(){
						System.out.println("匿名内部类");
					}
           	};
      	i.show();
    }
}
//测试类
public class OuterDemo{
    public static void main(String[] args){
    	Outer o=new Outer();
    	o.method();
        
    }
}

(3)匿名内部类在开发中的使用(应用)
当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名内部类过去,来简化传统的代码

//接口类
public interface Jumpping {
    void jump();
}
//接口实现类(猫)
public class Cat implements Jumpping{
    @Override
    public void jump() {
        System.out.println("猫跳起来了");
    }
}
//接口实现类(狗)
public class Dog implements Jumpping{
    @Override
    public void jump() {
        System.out.println("狗跳起来了");
    }
}
//接口操作类
public class JumppingOperator {
    public  void method(Jumpping j) {
        j.jump();
    }
}
//接口测试类
public class JumppingDemo {
    public static void main(String[] args) {
        //创建JumppingOperator对象,调用方法
        JumppingOperator jo=new JumppingOperator();

            Jumpping j=new Cat();
                jo.method(j);

            Jumpping j2=new Dog();
                jo.method(j2);

        //优化:1.不用再创建接口实现类(删掉Cat和Dog类也不影响)  2.不用再创建实现类对象
            jo.method(new Jumpping() {
                @Override
                public void jump() {
                    System.out.println("猫跳起来了");
                }
            });

            jo.method(new Jumpping() {
                @Override
                public void jump() {
                    System.out.println("狗跳起来了");
                }
            });
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值