Java初始化简介
一般来说,在Java中,每个类产生的编译代码都存在于它自己的独立文件中,该文件只有在使用程序代码时才会被加载,也就是说,类的代码只有在初次使用时才加载。但是,如果存在static的话,就不一样了,当访问static字段或static方法时,也会发生加载。最常见的static方法是构造器方法了,虽然没有显示写明static关键字。所以,更准确地讲,Java的类应该是在其任何static成员被访问时加载的。
Java继承的概念
Java面向对象的三大特征是继承、封装、多态。继承的概念顾名思义,类似父子关系,子继承父亲。继承通常被认为是is-a关系,即子类是一个父累,可以这样理解。例如,大黄鸭是一个鸭子。虽然继承是面向对象的一个重大特性,但是对于项目的架构来说,继承应该慎用,常用的模式有组合,组合即一个类中持有另外一个类的对象,例如我们要构造一个汽车时,总要持有发动机、门、窗户、轮子等这些类的具体对象,显然汽车不是一个发动机,也不是一个轮子,它们的关系是has-a的关系,因此需要使用组合模式来设计。在OOP中,使用继承的一个优点是它可以向上转型(upcasting),即子类可以持有父类的方法,或者说子类是一个父类,通过向上转型,进而引出了多态的优点,即当有方法被覆盖时,父类类型的子类对象可以从子类依次向上查找,知道遇到该方法便可调用,这一优点为程序的可扩展性奠定了基础,如要新建一个子类,只用重新覆盖父类中已有的某个方法即可,在调用时即可实现多态的特性。然而,继承的使用场合应该尽量谨慎,使用前应该问问自己是否需要向上转型,如果后续业务中,必须要进行向上转型,那么就使用继承;否则,大可不必使用继承。
那么,在继承这种设计模式中,程序的加载过程是怎么进行的呢?父类的构造方法会不会加载?如果有static字段或方法,又是如何加载呢?
含有继承的程序加载过程
下面,我们以一个继承关系的两个类来探讨该问题,类中包含有static字段。
首先,写出基类的代码:
package demo0812.demo1;
public class SupClass {
private int i=9;
protected int j;
public SupClass() {
System.out.println("i="+i+",j="+j);
j=39;
}
private static int x1=printInit("SupClass.x1 initialized");
protected static int printInit(String str) {
System.out.println(str);
return 47;
}
}
写出子类的代码:
package demo0812.demo1;
public class SubClass extends SupClass {
private int k=printInit("SubClass.k initialized");
public SubClass() {
System.out.println("k="+k);
System.out.println("j="+j);
}
private static int x2=printInit("SubClass.x2 initialized");
public static void main(String[] args) {
System.out.println("SubClass constructor");
SubClass subClass = new SubClass();
}
}
从上面的两个类代码可以看出,基类中含有一个static方法和一个static字段,另外还包含一个显示的构造方法。那么在程序执行过程中,当然先访问SubClass.main()方法,这是程序的入口,于是加载器开始启动并找出SubClass的编译代码(SubClass.class文件),然后,注意到该类有个关键字extends,说明它有个父类,于是,加载器便去加载父类的代码,即SupClass.class文件。加载器发现父类中含有一个静态字段,于是加载器先加载这个静态字段,同时也加载了静态方法,于是输出
SupClass.x1 initialized
,同时将x1的值赋为47。在加载完父类的静态区域以后,开始加载子类的静态区域,加载器于是看到,在子类中,也有一个静态字段x2,并且对它进行初始化,于是输出
SubClass.x2 initialized
,同时,将x2的值赋为47。这时,父类和子类的静态区都已经加载完成,于是,接着读取main函数,首先输出main中的第一行命令
SubClass constructor
接着,执行第二行命令,即对子类进行实例化,注意对子类实例化之前一定会对父类进行实例化,于是输出
i=9,j=0
接着,对子类进行按序执行,首先输出
SubClass.k initialized
并对k赋值为47,最后输出
k=47
j=39
来源:oschina
链接:https://my.oschina.net/u/2315247/blog/491540