您的位置:首页 > 编程语言 > Java开发

实例化子类之后发生了什么

2014-08-31 12:49 381 查看
当我们用SuperClass s=new SubClass()实例化一个子类对象时,发生了什么。首先我们要知道类加载的机制,这是一切实例化的基础。

classloader 加载类用的是全盘负责委托机制。

全盘负责:即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入

委托机制:先让parent(父)类加载器 (而不是super,它与parent classloader类不是继承关系)寻找,只有在parent找不到的时候才从自己的类路径中去寻找。

类加载还采用了cache机制:如果 cache中保存了这个Class就直接返回它,如果没有才从文件中读取和转换成Class,并存入cache,这就是为什么修改了Class但是必须重新启动JVM才能生效的原因。

1. 检测此Class是否载入过(即在cache中是否有此Class),如果有到8,如果没有到2

2. 如果parent classloader不存在(没有parent,那parent一定是bootstrap classloader了),到4
3. 请求parent classloader载入,如果成功到8,不成功到5
4. 请求jvm从bootstrap classloader中载入,如果成功到8
5. 寻找Class文件(从与此classloader相关的类路径中寻找)。如果找不到则到7.
6. 从文件中载入Class,到8.
7. 抛出ClassNotFoundException.
8. 返回Class.
按照以上规则,我们看如下代码:
class SuperClass {
public SuperClass() {
System.out.println("SuperClass of constructor");
m();
this.showname();
}
protected void m() {
System.out.println("SuperClass.m()");
}
protected void showname(){
System.out.println("now is "+this.getClass());
}
}
public class SubClass extends SuperClass  {
private int i = 10;
public SubClass() {
super.m();
System.out.println("SubClass of constructor");
// super.m();
m();
}
public void m() {
System.out.println("SubClass.m(): i = " + i);
}
private void m(int a){
}
public void showname(){
System.out.println("son father is "+super.getClass());
System.out.println("son is "+this.getClass());
}
<span style="white-space:pre">	</span>    public static void main(String[] args) {
<span style="white-space:pre">	</span>        SuperClass t = new SubClass();
<span style="white-space:pre">	</span>    }
<span style="font-family: Arial;">	}</span>

当我们实例化SubClass时,JVM会加载相关的类,包括子类,父类并保留父子关系。此时方法子类中的同名同参数列表方法m()实际上是对父类进行了重写。实例化顺序如下,父类中static—子类中static—父类中默认初始化—父类构造函数—子类默认初始化—子类构造函数。在这个过程中,任何对m()方法的合理调用都会调用子类的方法,即已经重写后的方法。除非super.m()调用,才会调用到父类的m方法,原因就是该方法已经被子类m覆盖。
this变量指向当前执行程序的对象,由于本程序实例化子类对象,所以所有this指向子类对象,父类中的this调用,会调用子类的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息