25. 转型问题
不管是向上或者向下,注意区分父类引用指向子类对象。
25.1向上转型 :
**通俗地讲即是将子类对象转为父类对象。此处父类对象可以是接口。
总结:
1、父类引用指向子类对象,而子类引用不能指向父类对象。
2、把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转换
3、需要注意的是向上转型时 操作的子类对象 会遗失除与父类对象共有的 其他 方法(子类和父类不同的方法)**
向上转型的好处 :
public class TestAnimal {
public static void main(String[] args) {
doLive(new Cat());
doLive(new Dog());
}
/*
* 向上转型的好处 : 这里以父类为参数,调有时用子类作为参数,就是利用了向上转型。
* 这样使代码变得简洁。不然的话,如果 doLive() 以子类对象为参数,则有多少个子类就需要写多少个函数。这也体现了 JAVA 的抽象编程思想。
*/
public static void doLive(Animal a){
a.live();
}
}
class Animal{
public String name;
public Animal(){
System.out.println("父类无参构造方法");
}
public void live(){
System.out.println("父类方法");
}
}
class Dog extends Animal {
public int age; //属性丢失
public Dog(){
System.out.println("先默认执行父类构造,再执行子类");
}
@Override
public void live() {
System.out.println("子类对象dog重写后的方法");
}
}
class Cat extends Animal {
public Cat(){
System.out.println("先默认执行父类构造,再执行子类");
}
@Override
public void live() {
System.out.println("子类对象cat重写后的方法");
}
}
25.2向下转型 :
把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转换
向下转型容易发生类型转换异常(java.lang.class.CastExpection)
为了避免这一情况,在向下转型前,通常需要用 instanceof 运算符,其用来判断 前面的引用 是否指向 后面类型的 对象
26.方法重写
26.1 满足条件
- 两个类中的两个方法
- 两个类必须是继承或者实现关系
- 方法签名完全相同
26.2 注意事项
- 若子类中出现与父类中某个静态方法同名的方法,会报错,会要求其也定义为static方法
27.多态
27.1 多态前提
类的继承
接口的实现
27.2 多态最终表现形式
父类的引用指向子类的对象
27.3 多态调用
- 若子类中存在重写,则会调用重写后的方法
- 多态引用调用会对子类的新增内容不可见
27.3.1 总结
- 多态调用成员变量时:
编译和运行都只找父类
- 多态调用成员方法时:
编译时先看父类,运行时找子类中重写过的方法
- 注意:
如果多态不配合方法的重写,那么多态就没有意义
27.3.2 作用
1、提高了代码的维护性(继承保证);
2、提高了代码的扩展性(由多态保证);
3、把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
28. final关键字
28.1 作用
-
final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
-
使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写
-
无论属性是基本类型还是引用类型,final 所起的作用都是变量里面存放的"值"不能变。
-
这个值,对于基本类型来说,变量里面放的就是实实在在的值,如 1,“abc” 等。
-
而引用类型变量里面放的是个地址,所以用 final 修饰引用类型变量指的是它里面的地址不能变,并不是说这个地址所指向的对象或数组的内容不可以变,这个一定要注意。
重点注意 :
例如:类中有一个属性是 final Person p=new Person(“name”); 那么你不能对 p 进行重新赋值,但是可以改变 p 里面属性的值 p.setName(‘newName’);
29. 抽象类
29.1 由abstract修饰的类称为抽象类
抽象类本身不可以被实例化,并且抽象类中不一定有抽象方法
抽象类中可以定义属性、构造器、普通方法等
29.2 由abstract修饰的方法称为抽象方法
抽象方法没有方法体,且必须存在于抽象类中
继承抽象类的具体子类必须重写类中所有的抽象方法,包括为其定义方法体
29.3 抽象类的子类问题
涉及到 具体子类 和 抽象子类
对于具体子类,要重写抽象父类所有的抽象方法,并按需求新增方法
对于抽象子类,不用重写,按需新增抽象或普通方法即可
补充 :
abstract 不能和 private final static native 等关键字一起使用
30. 接口
30.1特点
- 接口可以"理解"为是一个特殊的抽象类
- 接口是引用类型数据
- 类只能单继承,而接口可以被多实现
- 接口被称为功能的集合,一般为抽象功能的集合
- 接口不能被实例化,其使用只能根据具体的实现类对象调用
30.2 JDK变化
-
JDK1.7之前 :
接口中可存在公共的静态常量 和 公共的抽象方法
-
JDK1.8之后:
接口中新增默认方法,即default修饰,且默认方法可以带有方法体
注意 : 接口中静态方法只能通过接口名调用
30.3 接口和继承的区别
继承 :
子类一单继承父类,就有权使用父类成员,侧重点是拿过来使用,可以不进行重写
接口:
实现类一旦实现接口,就拥有接口中定义的功能,侧重点是拿过来先重写,然后再使用
接口本身还可以继承多个接口