代码当中体现多态性,其实就是一句话,父类引用指向子类对象。
格式:
父类名称 对象名 = new 子类名称();
或者:
接口名称 对象名 = new 实现类名称();
访问成员变量的两种方式:
1.直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上找。
2.间接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有则向上找。
在多态代码当中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有则向上找。
口诀:编译看左边,运行看右边。
对比一下:
成员变量:编译看左,运行还看左
非静态成员方法:编译看左,运行看右边
静态成员方法:编译看左,运行看左
向上转型一定是安全,没有问题的,正确的,但也有一个弊端:
对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
1.对象的向上转型,其实就是多态写法:
格式: 父亲名称 对象 = new 子类名称(); Animal animal = new Cat();
含义:右侧创建个子类对象,把它当做父类来看待使用。 创建了一只猫,当做动物看待,没问题。
注意事项:向上转型一定是安全的。从小范围转向了大范围,从小范围的猫,向上转换成为更大范围的动物。
类似于:
double num= 100; 1/正确,int --> double,自动类型转换。
2.对象的向下转型,其实是一个[还原]的动作。
格式:子类名称 对象名= (子类名称)父类对象;
含义:将父类对象,[还原]成为本来的子类对象。
Animal animal = new Cat(); /本来是描,向上转型成为动物
Cat cat = (Cat) animal; ,本来是描,已经被当做动物了,还原回来成为本来的描
注意事项:
a.必须保证对象本来创建的时候,就是猫,才能向下转型成为猫。
b.如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错。ClassCastException
类似于: int num = (int) 10.0;//可以 int num = (int) 10.5; /不可以,精度损失
如何才能知道一个父类的引用对象,本来是一个什么子类? instanceof
格式:
对象 instanceof 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。
例如:
if(aniaml instanceof Dog){
Dog dog = (Dog) animal;
dog.watchHouse();
}
final关键字代表最终,不可改变。
常见的四种用法:
1.用来修饰一个类
格式:
public final class 类名称{
//...
}
含义:当前这个类不能有任何的子类。
注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子)
2.用来修饰一个方法,这个方法就是最终方法,也就是不能覆盖重写
格式:
修饰符 final 返回值类型 方法名称(参数列表){
//...
}
注意事项:对于类,方法来说,abstract与final不能同时使用,因为矛盾。
3.修饰一个局部变量
一旦使用final关键字修饰局部变量,那么这个变量就不能进行更改。“一次赋值,终生不变”
对于基本类型来说,不可变说的是变量当中的数据不可改变。
对于引用类型来说,不可变说的是变量当中的地址值不可改变。
final Student stu = new Student("高圆圆");
stu = new Student("赵又廷");//错误,引用类型地址值不可变
stu.setName("高圆圆圆圆");//正确
4.修饰一个成员变量
1.成员变量具有默认值,所以使用final之后必须手动赋值。
2.对于final的成员变量,要么使用直接赋值,要么使用构造赋值,二者选其一。
3.必须保证类当中的所有重载的构造方法都最终会对final的成员变量进行赋值。
Java中有四种权限修饰符:
public > protrcted > (default) > private
同一个类 YES YES YES YES
同一个包 YES YES YES NO
不同包子类 YES YES NO NO
不同包非子类 YES NO NO NO
注意事项:(default)并不是default关键字,而是根本不写