这篇文章主要介绍了Java基类和派生类中各种方法的加载顺序(常见于面试题),本文直接给出代码实例和运行结果,给后给出了加载过程总结,需要的朋友可以参考下。
1. 构造类的实例对象前,先加载类本身。
2.若要加载类A,则先加载执行其父类B)的静态变量以及静态语句块(执行先后顺序按排列的先后顺序)。然后再加载执行类A的静态变量以及静态语句块。(并且对于所有的A的对象,加载A(及B)只会执行1次)
3.若需实例化类A,则先调用其父类B的构造函数,并且在调用其父类B的构造函数前,依次先调用父类B中的非静态变量及非静态语句块.最后再调用父类B中的构造函数初始化。然后再依次调用类A中的非静态变量及非静态语句块,最后调用A中的构造函数初始化。
4.而对于静态方法和非静态方法都是被动调用,即系统不会自动调用执行,所以用户没有调用时都不执行,主要区别在于静态方法可以直接用类名直接调用(实例化对象也可以),而非静态方法只能先实例化对象后才能调用。
基类静态语句块->派生类静态语句块->(若两个类都未被加载过,这个过程有且只有一次)
基类非静态语句块-基类构造函数->派生类非静态语句块->派生类构造函数->(每次构造都会出现)
被调用的(静态、非静态)方法。
追问:
先有父亲后有儿子,这句话不是只针对“构建对象”而言的吗,他也针对“类的加载”吗?我的理解是:对于构建对象的话, 的确是应该先构建父类对象,才能构建子类对象。但对于类的加载的话 ,不应该是看到内存中缺少了哪个类就应该加载哪个类的吗?
追答:
加载的时候也是一样的,当加载类A的时候,发现有父类B,就去搜索并加载B了, 这个时候还没有加载A中那些静态块,等B加载完了之后,才会返回来加载A, 也只有这样,程序才知道A中到底会有些什么方法,因为A中存在着由B继承而来的方法。 如果先加载了A,那么就会出现两种情况,一种是A中没有继承而来的方法, 另一种是加载B后再一次加载A继承而来的方法,那这样的Java就太差劲了,你说呢?
package com.company;
public class Main{
public static void main(String[] args){
A a1 = new A();
System.out.println("End of test a1 ");
A a2 = new A();
//a.aDisplay();
System.out.println("End of test a2");
}
}
class B{
//静态变量
static int i = 1;
//非静态变量
int j = 1;
//静态语句块
static {
System.out.println("Base Class B:static blocks i = " + i);
}
//构造函数
public B(){
i++;
j++;
System.out.println("Base constructor B: "+" i = " + i + ", j = " + j);
}
//非静态语句块
{
i++;
j++;
System.out.println("Base Class B:non-static blocks " + "i = " + i + ", j = " + j);
}
//非静态方法
public void bDisplay(){
i++;
System.out.println("Base Class B:static void bDisplay(): " + " i = " + i + " , j = "+j);
return ;
}
//静态方法
public static void bTest(){
i++;
System.out.println("Base Class B:static void bTest(): " + " i = " + i);
return ;
}
}
class A extends B{
//静态变量
static int i = 1;
//非静态变量
int j = 1;
//静态语句块1
static {
System.out.println("Derived Class A:static blocks i = " + i);
}
//构造函数
public A(){
super();
i++;
j++;
System.out.println("Derived constructor A: " + " i = " + i + " , j = " + j);
}
//静态语句块2
static{
i++;
System.out.println("Derived Class A:static blocks i = " + i);
}
//非静态语句块
{
i++;
j++;
System.out.println("Derived Class A:non-static blocks" + " i = " + i + " , j = " + j);
}
//非静态方法
public void aDisplay(){
i++;
System.out.println("Derived Class A:static void aDisplay(): "+" i = " + i + " , j = " + j);
return ;
}
//静态方法
public static void aTest(){
i++;
System.out.println("Derived Class A:static void aTest(): " + " i = " + i);
return ;
}
}
执行结果如下:(运行环境IntelliJ IDEA + jdk 1.8)
/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/bin/java...
Base Class B:static blocks i = 1
Derived Class A:static blocks i = 1
Derived Class A:static blocks i = 2
Base Class B:non-static blocks i = 2, j = 2
Base constructor B: i = 3, j = 3
Derived Class A:non-static blocks i = 3 , j = 2
Derived constructor A: i = 4 , j = 3
End of test a1
Base Class B:non-static blocks i = 4, j = 2
Base constructor B: i = 5, j = 3
Derived Class A:non-static blocks i = 5 , j = 2
Derived constructor A: i = 6 , j = 3
End of test a2
Process finished with exit code 0