2022.8.7
一、多态、运算符instanceof
在类继承或接口实现的情况下,通过使用任意子类的构造方法创建父类对象:Fu a =new Zi();或者将不同子类对象传入以父类为形参的方法,执行不同子类都需要的功能,将Zi a,传入public void method(Fu f){},使得一个方法可以满足所有子类的需求,提高代码的扩展性、复用性。
“编译看左边,执行看右边”
Fu a =new Zi();中,a在编译时执行Zi独有的方法会报错,但可以执行。
而a执行Fu和Zi共有的方法时,则由于Fu有方法而不报错,但执行时则执行Zi类的方法体。
运算符instanceof使用及向下转型,引用类型强转
Fu f = new Fu();
Zi z = new Zi();
Sun s = new Sun();
1、s instanceof Zi,判断s是不是Zi类,可以用来强转时避免出错
2、从子转成父类:Zi z = (Zi)f;
二、成员内部类、局部内部类、匿名内部类、成员位置、局部位置
内部类即类之内的类,分为成员内部类和局部内部类,内部类脱离外部类无法单独使用。
成员位置和局部位置,成员位置即在类中方法外的成员,供本类使用,局部位置即在方法中的成员,只供本类使用
成员内部类的使用分为两步:创建外部类对象,通过外部类对象创建内部类对象。内部类可以使用外部类的所有成员。
内部类编译后的结果为:
外部类$内部类.class
使用方法为:
Body body =new Body():
Body.Heart h= body.new Heart();
h即内部类对象,再调用属于h的或者body 的方法。
大部分的书籍,上述操作写为:
Body.Heart h= new Body().new Heart();,但是坏处是耦合度高,无法单独使用Body类,除非是static修饰的成员内部类。
局部内部类即在方法中的类,只能这个方法使用。局部内部类编译后的结果为:
外部类$(第几个局部内部类,可能有同名)内部类.class
匿名内部类,即在使用接口时进行实例化,但没有类名:
接口Fu,abstract void method();
Fu f = new Fu(){
public void method(){方法体;}
};
这样子,就变成了一个在构造方法实现Fu的匿名内部类,但只能用一次。
而形参也可以使用匿名内部类
public static void method(Fu f){};
method(new Fu(){
public void method(){方法体;}
});
以上都能改成Lambda表达式:
Fu f = (() -> {
方法体;
});
三、枚举类
枚举,在限定某个类型的所有值的范围时所用,例如一星期七天、一年四季,适合只有几个固定值的情况。保证这些数据正确避免非法数据。
枚举本质上是一个继承了java.lang.Enum的最终类,枚举限定的值则是通过:
public static final 类名 值 = new 类名(“值”,序号);以下方的构造方法构造成对象作为成员变量。
构造方法则是:
Private 类名(String 值, int 序号){
Super(值,序号);
}
这个构造方法是私有的,只能通过上方的值+序号进行构造,所以不能对外创建对象,只能自己创建。
网页中传入的数字如果需要匹配为枚举,则通过类名.values()[数字]),来匹配网页中传入的数字
四、Object类、toString()、equals()、==
是所有类的默认父类,主要方法有toString()、equal()
toString()在Object类中,打印的是包名、类名、哈希码在内的地址值,而常见的类如String、ArrayList,都重写了toString,所以可以直接打印出值,但别的类或自建类,则需要自己重写才可以。
==是一个运算符,判断两个变量的值是否相等,基本数据类型直接比较值,因为值直接在栈内存中生成,而引用类型则比较栈内对象对应的引用的内存首地址。
equals()源码是返回==,而String重写了这个方法,String类型中,==比较的是两者的地址值,equals()则比较两者的值。String类型数据在equals()时,会先判断两者地址值是否相等,如果相等则true,不相等则判断值,值相等亦是true。
其他类或者自建类如果也需要使用equals()比较值,则需要重写equals方法才能用以比较。equals()和hashCode()在类中被重写后,都会以类的对象来作为equals比较和生成hashCode的依据。