多态的应用

多态的应用

方法: 返回值类型 参数列表 方法名

多态的两种实现方式

  • 使用父类作为方法形参实现多态
  • 使用父类作为方法返回值实现多态

当这个作为参数的父类是普通类或者抽象类时,构成继承多态
当这个作为参数的父类是一个接口时,构成接口多态

多态作为形参(形式参数)

基本类型

满足类型转换的规则

引用类型

普通类

当一个形参希望我们传入的是一个普通类时,我们实际上传入的是该类的对象/匿名对象

抽象类

当一个形参希望我们传入的是一个抽象类时,我们实际上传入的是该类的子类对象/子类匿名对象

接口

当一个形参希望我们传入的是一个接口时,我们实际上传入的是该类的实现类对象/实现类匿名对象

多态作为返回值

返回值类型

基本类型

引用类型

普通类

当一个方法的返回值是一个普通的类时,实际上返回的是该类的对象,我们可以使用该类的对象接收

抽象类

当一个方法的返回值是一个抽象类时,实际上返回的是该抽象类的子类对象,我们可以使用该抽象类接收

接口

当一个方法的返回值是一个接口时,实际上返回的是该接口的实现类对象,我们可以使用接口接收

当方法的返回值类型是引用类型的时候,可以使用链式调用

注意: 当一个方法的形参是引用类型的时候,建议养成一个好的习惯: 做非空判断

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();
	}
}

实例化对象加载顺序

一旦实例化一个对象,其执行顺序,首先:

在不涉及继承的前提下,当首次加载类时,按照如下顺序执行:

  1. 按照出现顺序先后执行静态成员变量定义与静态块;
  2. 按照出现顺序先后执行动态成员变量定义与动态块;
  3. 执行构造函数;
    再次实例化对象时只执行第2、4步即可;

在涉及到继承时,按照如下顺序执行:

  1. 执行父类的静态成员变量定义与静态块,执行子类的静态成员变量与静态块
  2. 执行父类非静态成员变量定义与动态块,执行父类构造方法;
  3. 执行子类的非静态成员变量定义与动态块,执行子类构造方法;
  • 注意:父类构造方法中用到的方法如果已被子类重写,那么在构造子类对象时在调用父类构造函数中使用子类重写的方法。

在类加载机制中,更加详细讲解到实例化对象加载机制需要结合jvm内部运行机制的解析一起分析。

posted @ 2019-04-22 19:27  凄夜听雨  阅读(608)  评论(0)    收藏  举报