学完本次课程后,你能够:
实现方法重写 深入理解继承相关概念
了解Object类
会使用重写实现多态机制
会使用instanceof运算符
会使用向上转型
会使用向下转型
什么是方法重写
方法的重写或方法的覆盖(overriding)
1.子类根据需求对从父类继承的方法进行重新编写
2.重写时,可以用super.方法的方式来保留父类的方法
3.构造方法不能被重写
方法重写规则
方法名相同
参数列表相同
返回值类型相同或者是其子类
访问权限不能严于父类
父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法
子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法(注:静态方法中无法使用super)
父类的私有方法不能被子类覆盖
不能抛出比父类方法更多的异常
方法重写vs方法重载
Object类
Object类是所有类的父类
Object类被子类经常重写的方法
Object类的equals()方法
1.比较两个对象是否是同一个对象,是则返回true
2.操作符==
简单数据类型,直接比较值。如1==2
引用类型,比较两者是否为同一对象
(1)Object类的equals()方法与==没区别
(2)当有特殊需求,如认为属性相同即为同一对象时,需要重写equals()
(3)Java.lang.String重写了equals()方法,把equals()方法的判断变为了判断其值
instanceof用于判断一个引用类型所引用的对象是否是一个类的实例
为什么使用多态
频繁修改代码,代码可扩展性、可维护性差
使用多态优化
同一种事物,由于条件不同,产生的结果也不同
多态:同一个引用类型,使用不同的实例而执行不同操作
方法重写是实现多态的基础
抽象方法
抽象方法没有方法体
抽象方法必须在抽象类里
抽象方法必须在子类中被实现,除非子类是抽象类
向上转型
向上转型:父类的引用指向子类对象,自动进行类型转换
//测试方法
Pet pet = new Dog();
pet.setHealth(20);
Master master = new Master();
master.cure(pet);
<父类型> <引用变量名> = new <子类型>();
此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法,不是父类的方法
此时通过父类引用变量无法调用子类特有的方法
向下转型
向下转型:将一个指向子类对象的父类引用赋给一个子类的引用,即:父类类型转换为子类类型。需强制类型转换
如果需要子类特有的方法,怎么办?
Dog dog=(Dog)pet;//将pet 转换为Dog类型
dog. catchingFlyDisc();//执行Dog特有的方法
<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
在向下转型的过程中,如果没有转换为真实子类类型,会出现类型转换异常
instanceof
如何减少在向下转型的过程中,没有转换为真实子类类型的类型转换异常?
Java中提供了instanceof运算符来进行类型的判断
使用instanceof时,对象的类型必须和instanceof后面的参数所指定的类在继承上有上下级关系
多态的应用
使用父类作为方法的形参,是Java中实现和使用多态的主要方式
使用父类作为方法的返回值,也是Java中实现和使用多态的主要方式
当父类方法不足以满足子类需求时,在子类中可以对父类中的方法进行重写,方法重写有如下规则:
1)在子类中重写
2)重写方法与父类方法方法名相同
3)重写方法参数列表与父类方法参数列表相同
4)重写方法的返回值类型和父类方法返回值类型相同或者其子类
5)重写方法的访问修饰符不能严于父类方法的访问修饰符
@Override 注解,说明该方法是重写的方法
友情提醒:
一个对象在调用方法的时候,先从自己类中查找,如果有就调用自己类中的方法
如果自己类中没有找到调用的方法,就找父类,父类有就调用父类中的方法,如果父类没有,继续往上找父类的父类....直到找到Object类中
如果Object类中没有你要调用的方法,那就报错
Object类中的equals()方法比较的是两个对象的内存地址值,因为查看equals()方法底层代码得知,其方法体内部是使用==比较两个对象
==比较基本数据类型中的数值,也可以比较引用数据类型,比较引用数据类型时,比较的是引用数据类型在内存中的地址值
toString()方法是Object类中的一个,以字符串的形式返回对象在内存中的地址值,格式如下:
getClass().getName() + "@" + Integer.toHexString(hashCode())
多态:同一个父类引用,指向不同的子类实例,实现的操作不同(实现操作不同的前提是在子类中对父类的方法进行了重写)
通过父类引用调用方法,从代码表面上看是调用父类中的方法,实际上调用的是指向的子类中重写后的方法
向下转型过程中有可能出现异常,将父类引用指向的对象没有转换为其真实的子类对象,会报ClassCastException(类型转换异常)
为了避免在向下转型过程中出现类型转换异常,所以在转型前先对父类引用指向的子类进行判断,判断父类引用指向的是哪一个子类实例,这个使用instanceof运算符实现
父类引用 instanceof 子类类名:如果父类引用执行的是你指定的子类,返回true,否则返回false
抽象类:使用abstract修饰的类为抽象类
1)抽象类的定义与前面定义普通类是一样的,可以定义属性、构造方法、get/set方法、重写toString()方法、其他普通方法
2)抽象类中可以定义抽象方法,也可以不定义抽象方法
3)抽象类一般用于定义父类,所以在子类中必须重写父类中所有的抽象方法,如果不重写,那么子类也要定义为抽象类
4)抽象类不能直接通过new的形式来实例化,可以通过多态的形式来创建其引用
抽象类类名 引用名= new 子类();
输出属性信息
既然在多态中,父类引用调用给的方法实际上是指向的子类中重写后的方法,那么在父类中定义的方法可以不定义方法体,将方法定义为抽象方法
抽象方法:使用abstract修饰的方法为抽象方法
1)抽象方法没有方法体
2)抽象方法所在的类要定义为抽象类
多态的应用:
1)使用父类作为方法的形参,是Java中实现和使用多态的主要方式
2)使用父类作为方法的返回值,也是Java中实现和使用多态的主要方式
NullPointerException:空指针异常,当使用一个null对象调用方法时,会报空指针异常