多态的应用
方法: 返回值类型 参数列表 方法名安全
多态的两种实现方式
- 使用父类做为方法形参实现多态
- 使用父类做为方法返回值实现多态
当这个做为参数的父类是普通类或者抽象类时,构成继承多态 当这个做为参数的父类是一个接口时,构成接口多态jvm
多态做为形参(形式参数)
基本类型
知足类型转换的规则ide
引用类型
普通类
当一个形参但愿咱们传入的是一个普通类时,咱们实际上传入的是该类的对象/匿名对象函数
抽象类
当一个形参但愿咱们传入的是一个抽象类时,咱们实际上传入的是该类的子类对象/子类匿名对象spa
接口
当一个形参但愿咱们传入的是一个接口时,咱们实际上传入的是该类的实现类对象/实现类匿名对象code
多态做为返回值
返回值类型对象
基本类型
引用类型
普通类
当一个方法的返回值是一个普通的类时,实际上返回的是该类的对象,咱们能够使用该类的对象接收继承
抽象类
当一个方法的返回值是一个抽象类时,实际上返回的是该抽象类的子类对象,咱们能够使用该抽象类接收接口
接口
当一个方法的返回值是一个接口时,实际上返回的是该接口的实现类对象,咱们能够使用接口接收io
当方法的返回值类型是引用类型的时候,能够使用链式调用
注意: 当一个方法的形参是引用类型的时候,建议养成一个好的习惯: 作非空判断
public class ArgsDemo01 { public static void main(String[] args) { // 需求: 访问学生类中的 study方法 Student s = new Student(); s.study(); new Student().study(); // 需求: 访问StudentDemo中的method方法 StudentDemo sd = new StudentDemo(); // sd.method(null); // 当一个形参但愿咱们传入的是一个普通类时,咱们实际上传入的是该类的对象/匿名对象 // 习惯: 在写方法的时候,若是方法的形参是引用类型,记住要作非空判断,提升程序的安全性 new StudentDemo().method(new Student() { @Override public void study() { System.out.println("Student 子类 study"); } }); } } class Student { public void study() { System.out.println("Student.study()"); } } class StudentDemo { // Student s = null; public void method(Student s) { // Student s = new Student(); // if (s != null) { // s.study(); // } if (s == null) { throw new NullPointerException("对象不可以为null"); } s.study(); } }
实例化对象加载顺序
一旦实例化一个对象,其执行顺序,首先:
在不涉及继承的前提下,当首次加载类时,按照以下顺序执行:
- 按照出现顺序前后执行静态成员变量定义与静态块;
- 按照出现顺序前后执行动态成员变量定义与动态块;
- 执行构造函数; 再次实例化对象时只执行第二、4步便可;
在涉及到继承时,按照以下顺序执行:
- 执行父类的静态成员变量定义与静态块,执行子类的静态成员变量与静态块
- 执行父类非静态成员变量定义与动态块,执行父类构造方法;
- 执行子类的非静态成员变量定义与动态块,执行子类构造方法;
- 注意:父类构造方法中用到的方法若是已被子类重写,那么在构造子类对象时在调用父类构造函数中使用子类重写的方法。
在类加载机制中,更加详细讲解到实例化对象加载机制须要结合jvm内部运行机制的解析一块儿分析。