11、方法的重写
重写的规定
@Override
权限修饰符返回值类型方法名(形参列表){
// 方法名
}
- 子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 方法体(具体的实现不同)
- 修饰符:
- 范围可以扩大但不能缩小
- 抛出的异常:范围可以被缩小,但不能扩大
- 特殊情况:
- 子类不能重写父类private的方法
- 返回值类型:
- 父类被重写的方法返回值为void,则子类重写的方法的返回值类型只能是void
- 父类被重写的方法的返回值是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
- 父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法的返回值类型必须是相同的基本数据类型
- 子类和父类的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写,随着类加载而加载)
- 静态方法:方法的调用只和左边,定义的数据类型有关(即调用的数据类型)。所以重写只能是非静态方法
- 非静态方法,子类重写父类的方法,重写之后都执行子类的方法
重载是同一类里,方法名相同,参数类型不同。 重写是子父类间,子类重写父类的方法,alt+insert,方法名相同,方法内容不同。使用public方式,且不使用static方式。
为什么需要重写
- 父类的功能子类不一定需要,或者不一定满足
12、多态(声明对象时的多种形态)
- 父类的引用指向子类的对象 (向上转型) (狗是动物)
Father f = new Son();
- (方法)编译看左边,运行看右边
- 多态是方法的多态,属性没有多态(编译、运行都看左边)
什么是多态性
- 父类的引用指向子类的对象
多态的使用:虚拟方法调用
- 当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法
- 编译看左边,运行看右边
- 有了对象的多态性之后,我们在编译期,只能调用父类中声明的方法,但是在运行期间实际执行的是子类重写父类的方法(父类中没有,子类中新加的方法无法通过编译!!!)
多态性的使用前提
- 必须继承
- 有方法重写
- 父类引用子类的对象
- 只适用于方法,不适用于属性
静态绑定和动态绑定
静态绑定:重载时的调用地址在编译器就绑定了
动态绑定:对于多态,只有等到方法调用的那一刻才知道调用的是什么
13、向上转型和向下转型
- 前提条件:两种类型必须有继承关系
- 向上转型就是类的多态
- 向上转型(子类对象转为父类对象—从右往左看):
- 父类引用指向子类对象
- 父类中被子类重写的方法会被子类替换掉,会丢失子类自己所特有的方法
Father a = new Son()
- 可以调用父类类型中的所有成员,但不能调用子类的特有成员
- 向下转型(父类对象转为子类对象—从右往左看):
- 使用场景:
由于向上转型时Person p = new Man();对象p被编译器识别为父类对象而无法调用子类对象所特有的属性和方法,所以需要使用向下转型(其实已经在内存中加载过了,但是由于指向的引用类型限制不能使用)- 子类对象指向父类引用
Man m = (Man)p
需要强制转换,丢失父类被子类所重写掉的方法- 使用强制类型转换时有可能会出现转换失败的问题
向下转型的常见问题
注意:父类对象没有子类对象所特有的功能,不能向下转
Person p = new Person();
Man m = (Man)p; // 编译通过,运行不通过
// Person中没有Man所特有的方法
Object obj = new Woman();
Person p = (Person)obj; // 编译通过,运行也通过
instanceof和类型转换
- 使用场景:为了防止在向下转型之前出现异常
- 用于判断左边对象是否是右边类/接口的实例
对象 instanceof 类
因为向上转型所以实际指向的是Student类