java中类加载的分析

本篇文章是看《effective java》第17条有感,在其基础上还是有所扩展。本篇文章主要探究的是:在类继承之后,创建子类对象,对父类构造器的调用,以及类初始化的顺序(即父类域的初始化,子类域的初始化)。对于这样的分析,别什么理论不理论,我的解决方案就是先编个程看看,实际情况是什么样,要是和自己理解的不一样,再查资料,补充自己的理论体系。所以不废话了,看代码!

class SuperClass{
	public static String superStaticField="父类===静态域";
	public String superField="父类===变量";
	static{
		System.out.println(superStaticField);
		System.out.println("父类===静态初始化块");
	}
	{
		System.out.println(superField);
		System.out.println("父类===初始化块");
	}
	public SuperClass(){
		System.out.println("父类构造器");
	}
}
	public class SubClass extends SuperClass {
	public static String subStaticField="子类===静态域";
	public String subField="子类===变量";
	static{
		System.out.println(subStaticField);
		System.out.println("子类===静态初始化块");
	}
	{
		System.out.println(subField);
		System.out.println("子类===初始化块");
	}
	public SubClass(){
		
		System.out.println("子类构造器");
	}
	public static void main(String[] args){
		System.out.println("----------------");
		new SubClass();
	}
}

输出的结果是:

父类===静态域
父类===静态初始化块
子类===静态域
子类===静态初始化块
----------------
父类===变量
父类===初始化块
父类构造器
子类===变量
子类===初始化块
子类构造器

从代码到输出结果我们可以看到一清二楚,我们实现了类的继承,那首先要先有个父类,所以java做的也对,就是先初始化父类,先将父类的.class文件加载进来,有了父类然后再加载子类。由于静态域是类固有的域,在没有对象之前就已经存在,是在编译好后就已存在的域,所以在编译好后,父类的静态域和子类的静态域都已经初始化好了,所以先打印的就是静态域。然后开始类的一般变量的初始化,当然首先是从父类开始的,这也非常理解,只有在父类的所有情况全部稳定之后,子类才能进行状态的初始化,要不然子类就没法用父类的东西了!

   然后我们再做个试验,把main方法里的所有语句都注释掉是什么情况,你会看到只有分割线(--------------)上面的输出了。这也刚好证实了,类的静态域是在编译时候就已经初始化存在了的,是与类共生的,即使是没有创建对象也能够使用! 这有相当的好处,这也是《effective java》里讲的另一条,就是静态工厂的说法,在这里就不展开了。

下面我们从这个例子中衍生出其他的问题,其实也是继承出现的问题,为了突出这个问题,下面让我把代码简化。

import java.util.*;;
class Super{
	public Super(){
		overrideMe();
	}
	public void overrideMe(){
	}
}
public class Sub extends Super{
	private final Date date;
	Sub(){
		date=new Date();
	}
  public void overrideMe(){
		System.out.println(date);
	}
	public static void main(String[] args){
                System.out.println("------输出:");
                Sub sub=new Sub();
		sub.overrideMe();
	}
}
这个输出是什么呐?

-------输出:

null
Fri Mar 27 15:59:56 CST 2015

第一个输出是null,原因就是从在加载父类构造器的时候,父类构造器调用了overrideMe()方法,此方法在子类中被覆盖,所以在调用的时候就调动了还没有初始化的date,当然就是null了。这个问题其实分析起来并不难,主要讨论的就是我们继承java中的工具类的时候,有没有考虑到会出现这种情况,以及如何避免这种情况的发生。《effective java》的做法是尽量使用组合的形式来扩展我们的类!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值