Java 代码块与代码加载顺序
本文首先介绍几个基本的名次,然后介绍了三种代码块的特性和使用方法。
在面试大型公司时,如果遇到大型国企或者大的互联网私企,笔试中经常遇到代码块和代码加载顺序的笔试题。这里做一个总结,也方便各位小伙伴飙车不会飘。
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄
-
名词解释
class Demo{ String x;// 非静态成员变量,又称为属性,对该类不同的对象来说,属性互不相同
static int y = 32;// 类变量,一个类中只有一个该变量,该类不同的对象共享同一个静态成员变量
public static void main(String[] args){ int z = 0;// 局部变量,只在方法内部可见,在方法结束后由垃圾收集器自动回收
} }
-
局部代码块
public class 局部代码块 {
public static void go() { // 局部代码块 { int age = 30; System.out.print("go: " + age); } } public static void main(String[] args) { go(); }
}
-
构造代码块
public class A { int i = 1; int initValue;//成员变量,初始化交给代码块来完成
A(){ System.out.println("构造方法在代码块执行后运行"); } { System.out.println("代码块从上至下依次运行"); //代码块的作用体现于此:在调用构造方法之前,用某段代码对成员变量进行初始化。 //而不是在构造方法调用时再进行。
for (int i = 0;i < 100;i ++) { initValue += i; } } { System.out.println(initValue); System.out.println(i);//此时会打印1
int i = 2;//局部变量,和成员变量不冲突,但会优先使用代码块的变量
System.out.println(i);//此时打印2 //System.out.println(j);//提示非法向后引用,因为此时j的的初始化还没开始。
} int j = 2; { System.out.println(j); System.out.println(i);//代码块中的变量运行后自动释放,不会影响代码块之外的代码
} } public class 构造代码块 { @Test public void test() { A a = new A(); } }
执行结果
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。代码块从上至下依次运行 4950
1
2
2
1 构造方法在代码块执行后运行
-
静态代码块
public class 静态代码块 { @Test public void test() { C c1 = new C(); C c2 = new C(); //结果,静态代码块只会调用一次,类的所有对象共享该代码块
System.out.println("我是普通方法"); } } class C{ C(){ System.out.println("构造方法调用"); } { System.out.println("代码块调用"); } static { System.out.println("静态代码块调用"); } }
调用结果:
静态代码块调用
代码块调用
构造方法调用
代码块调用
构造方法调用
我是普通方法
执行顺序 静态代码块 —–> 构造代码块 ——-> 构造方法
-
笔试题
public class HelloA { public HelloA(){ System.out.println("HelloA"); } { System.out.println("I'm A class"); } static { System.out.println("static A"); } } public class HelloB extends HelloA { public HelloB(){ System.out.println("HelloB"); } { System.out.println("I'm B class"); } static { System.out.println("static B"); } public static void main(String[] args) { new HelloB(); } }
执行结果:
分析:首先要知道静态代码块是随着类的加载而加载,而构造代码块和构造方法都是随着对象的创建而加载。 1,在编译HelloB.java时,由于HelloB 继承 HelloA,先加载了HelloA类,因此HelloA类的静态代码块首先执行,而后加载HelloB类,HelloB类的静态代码块执行,这没什么好说的。 2,然后创建HelloB的对象,大家都知道构造代码块优先于构造方法执行,这时候问题来了,这时应该先看HelloB类的构造方法,HelloB类里的构造方法里有一句隐式的super()首先被执行,所以找到HelloA类的构造方法,而HelloA类的构造方法中也有一句隐式的super()执行(调用Object类的构造方法),并没有什么返回结果,接下来才是在执行HelloA类构造方法的方法体前先执行了HelloA类的构造代码块(I'm A class),再执行HelloA类构造方法的方法体(也就是Hello A),最后又回到HelloB类的构造方法中,这时HelloB类的super()已经执行完了,在执行HelloB类构造方法的方法体前先执行HelloB类的构造代码块(I'm B class),再执行子类构造方法的方法体(HellB)。 无继承初始化顺序: 有继承初始化顺序: 接下来看一道阿里笔试题:
public class B{ public static B t1 = new B(); public static B t2 = new B(); { System.out.println("构造块"); } static { System.out.println("静态块"); } public static void main(String[] args) { B t =new B(); } }
执行结果:
-
总结
-
Reference
更多精彩