实例化子类之后发生了什么
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.
按照以上规则,我们看如下代码:
当我们实例化SubClass时,JVM会加载相关的类,包括子类,父类并保留父子关系。此时方法子类中的同名同参数列表方法m()实际上是对父类进行了重写。实例化顺序如下,父类中static—子类中static—父类中默认初始化—父类构造函数—子类默认初始化—子类构造函数。在这个过程中,任何对m()方法的合理调用都会调用子类的方法,即已经重写后的方法。除非super.m()调用,才会调用到父类的m方法,原因就是该方法已经被子类m覆盖。
this变量指向当前执行程序的对象,由于本程序实例化子类对象,所以所有this指向子类对象,父类中的this调用,会调用子类的方法。
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调用,会调用子类的方法。
相关文章推荐
- Git clone之后你的硬盘上究竟发生了什么?
- 在浏览器中输入Google.com并且按下回车之后发生了什么?
- malloc()之后,内核发生了什么?
- 当你在浏览器中输入 google.com 并且按下回车之后发生了什么?
- 从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
- 【计算机基础】当你在浏览器中输入Google.com并且按下回车之后发生了什么?
- 在 EBS Form 查找界面点 "Find" 之后都发生了什么?
- 在浏览器中输入Google.com并且按下回车之后发生了什么?[转]
- malloc()之后,内核发生了什么?【转】
- malloc()之后,内核发生了什么?
- 页面缓存过期之后会发生什么?
- 在浏览器里输入网址,按下回车键之后发生了什么
- 在浏览器里输个地址,按下回车之后发生了什么
- 当你在浏览器中输入Google.com并且按下回车之后发生了什么?
- 当你在浏览器中输入Google.com并且按下回车之后发生了什么
- 当你在浏览器中输入Google.com并且按下回车之后发生了什么?
- 从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
- 当你在浏览器中输入baidu.com并且按下回车之后发生了什么?
- 当我们游览网页的时候, 在输入链接点击回车之后到看到新网页这中间究竟发生了什么?
- malloc()之后,内核发生了什么?