【预习笔记】一道很有趣的有关java类加载初始化的题目

12 篇文章 0 订阅
public class classInit {

	public static void main(String[] args) {
		sampleA.showNum();
	}
}

class sampleA{
	
	public static sampleA sa = new sampleA();
	public static int num;
	public static int num2 = 250;
	
	public sampleA(){
		this.num = 110;
		this.num2 = 110;
	}
	
	public static void showNum(){
		System.out.println(num);
		System.out.println(num2);
	}
}

上面这题我第一次给出的运行结果是:110 110

但是是错的。因为设计到类加载初始化的问题。

能够触发初始化的条件:

1)创建类的实例
2)访问类的静态变量
3)访问类的静态方法
4)当初始化一个类时,发现其父类还未初始化,则先出发父类的初始化
5)虚拟机启动时,定义了main()方法的那个类先初始化

上面这段代码,是调用了sampleA的静态方法,因此触发初始化,但是初始化的第一行又调用了构造函数,因此,整个流程如下所示:


然后针对这几个条件实验其他几种情况下的初始化触发:


创建对象的时候

public class classInit2 {
	public static void main(String[] args) {
		new sampleB().showNum();
	}
}
class sampleB{
	
	public static sampleB sa = new sampleB();
	public static int num;
	public static int num2 = 250;
	
	public sampleB(){
		this.num = 110;
		this.num2 = 110;
	}
	
	public static void showNum(){
		System.out.println(num);
		System.out.println(num2);
	}
}

输出:110 110

可以发现,当调用构造函数的时候,立即完成初始化,然后在进入构造函数进行赋值。若把构造函数中的num2赋值注释掉,输出结果将为:110 250


虚拟机启动时,main方法所在的类先做初始化

public class classInit2 {
	
	public static classInit2 ci = new classInit2();
	public static int num;
	public static int num2 = 250;
	
	public classInit2(){
		num = 110;
		num2 = 110;
	}
	
	public static void showNum(){
		System.out.println(num);
		System.out.println(num2);
	}
	
	public static void main(String[] args) {
		classInit2.showNum();
	}
}

输出与第一个例子相同,也是 110 250

最后总结一下java类加载的过程

加载->验证->准备->解析->初始化->使用->卸载。


大概的解释:

加载:通过类的全限定名获取二进制的字节流,将此字节流所代表的静态存储结构转化为方法区的数据结构,在java堆中生成一个java.lang.class作为方法区中数据结构的访问入口。

验证:验证这个字节流是无害的,虽然java编译器会阻止大多数有害代码产生(如数组越界),但是字节流可以直接手动编写,虚拟机需要验证字节流是安全的对虚拟机没有破坏作用的字节流。

准备:将类的静态变量初始化为默认值。

解析:将符号引用转换为直接引用。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值