面试题:类初始化过程,实例初始化过程代码的执行顺序

类初始化过程,实例初始化过程代码的执行顺序

首先有以下代码:

public class ClassTest {
    
    
	public static void main(String[] args) {
    
    
		 Son s1=new Son(); 
		 System.out.println(); 
		 Son s2=new Son();
	}
		
	static {
    
    
		System.out.println("(11)main方法所在的类");
	}
}
class Father{
    
    
	private int i=test();
	private static int j=method();
	
	static {
    
    
		System.out.println("(1)父类中静态代码块");
	}
	Father(){
    
    
		System.out.println("(2)父类构造方法");
	}
	
	{
    
    
		System.out.println("(3)父类代码块");
	}
	
	public int test() {
    
    
		System.out.println("(4)父类成员方法-赋值语句");
		return 1;
	}
	
	public static int method() {
    
    
		System.out.println("(5)父类静态成员方法-赋值语句");
		return 1;
	}
}
class Son extends Father{
    
    
	private int i=test();
	private static int j=method();
	
	static {
    
    
		System.out.println("(6)子类中静态代码块");
	}
	Son(){
    
    
		System.out.println("(7)子类构造方法");
	}
	
	{
    
    
		System.out.println("(8)子类代码块");
	}
	
	public int test() {
    
    
		System.out.println("(9)子类成员方法-赋值语句");
		return 1;
	}
	
	public static int method() {
    
    
		System.out.println("(10)子类静态成员方法-赋值语句");
		return 1;
	}
}

请写出以上代码的运行结果。

题目解析:
首先我们可看到我们定义了一个Father类和它的子类Son类,它们类中的结构大致一致,分别有静态代码块,构造方法,代码块,成员方法,静态成员方法,要求输出它们的执行先后顺序。
执行结果:
在这里插入图片描述
也就是:
第一次实例化子类:

  • 父类静态成员方法->父类静态代码块->子类静态成员方法->子类静态代码块->子类私有成员方法
  • ->父类代码块->父类构造方法->子类私有成员方法->子类代码块->子类构造方法
  • 第二次实例化:
  • 子类成员方法->父类代码块->父类构造方法->子类成员方法->子类代码块->子类构造方法

类初始化过程:(5)(1)(10)(6)过程,(11)暂且排除

  • 一个类要创建实例需要先加载并初始化该类。
  • 注意:main方法所在的类需要先加载和初始化(所以11先执行)
  • 一个子类要初始化需要先初始化父类(所以第一次new Son类时会先初始化Father类)
  • 类初始化会调用clinit()方法 :
  •  由静态类变量显示赋值代码和静态代码块组成  只执行一次
    
  •  赋值代码和静态代块的执行顺序会由它们的位置决定
    
  • clinit方法只执行一次。

实例初始化过程: (9)(3)(2)(9)(8)(7)过程

  • 调用init()方法 可能可能有多个,几个构造器就有几个init()方法
  • 由非静态实例变量显示赋值代码和非静态代码块组成
  • super()->非静态赋值->非静态代码块->无参构造器,test()会覆盖父类中的代码,静态的method不能被重写。

方法的重写: 过程(9)

  • Son继承的父类的test方法,实际上重写了父类的test方法,所以i=test()其实是执行的是子类重写的父类的方法。
  • 静态的method方法不能被重写,final修饰的方法,private修饰的子类不可见的方法也不能被重写。

对象的多态性:

  • 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码。
  • 非静态方法默认的调用对象是this。

猜你喜欢

转载自blog.csdn.net/qq_45273552/article/details/109254128