new的后面做了什么?new 干了至少14件事--Java极限内存分析2
2009-04-10 12:21
351 查看
主程序:
父类:
子类:
内存分析:
1. 进入ClassLoader的loadClassInternal(String name)方法,加载Child类.
2. 同1,加载Parent类.
3. 初始化Parent的静态成员变量.Parent.a=1;
4. 调用Parent的静态代码块.Parent.a=2;执行方法p1();此时,调用的p1方法是Parent类的.所以输出Parent-a: 2.实际调用了Parent.p1(Parent.a);
5. 初始化Child的静态成员变量.Child.a=11;
6. 调用Child的静态代码块.Child.a=21;执行方法p1();此时调用的p1方法是Child类的.所以输出Child-a: 21.实际调用了Child.p1(Child.a);
7. 此时,类的加载,以及静态成员变量,静态语句块执行完毕.
8. 下面才真正开始进入new Child();
9. 首先进入的当然是Child的无参构造器中的super(a);这一句.
10. 进入Parent的Parent(int a)这个构造器.
11. 这个构造器其实是有隐式的super();这一句的.他是去调用了java.lang.Object的无参构造器,再向里,就是JVM的内幕了,我们就不参与了.
12. 调用完父类的构造器之后,下一步工作就是初始化成员变量.因此Parent的成员变量b=3执行.
13. 执行Child的动态语句块.b=4的赋值自然是Parent对象的成员变量b=4;一定注意,此时Child的成员变量b=0;调用p1()方法,由于是静态的,所以输出Parent自己的东西.调用p2()方法的时候,动态方法被重写,多态存在,所以这里输出的Child-b: 0,很明显,这里调用了子类的方法(p2);
14. 动态语句块执行完,就该执行Parent的构造器中super()之后的语句了.这里要注意,虽然Parent(int a)这个构造器中没有代码,但隐式的有一个super();由于后面再没有代码,所以Parent(int a)这个构造器就算执行完毕了,下面进入子类Child的构造器.
15. 当然,还是成员变量的初始化,b=31.
16. 然后,执行动态语句块,b=41.
17. 调用p1方法,是Child的p1方法.所以输出Child-a: 21;
18. 进入p2方法,调用的方法是Child的p2()方法,此时Child的成员变量b=41,当然输出的是Child-b:41;
19. 当这些过程全部执行完毕之后,整个构造器就算执行完毕了.
看看上面这些过程,new一个对象需要耗费多少的精力?
让我们看一看顺序:
加载子类, 加载父类, 初始化父类静态成员变量, 执行父类静态语句块, 初始化子类静态成员变量, 执行子类静态语句块, 调用子类的构造器, 调用父类的构造器, 初始化父类的成员变量, 执行父类的动态语句块, 执行父类构造器中的其他代码, 初始化子类的成员变量, 执行子类的动态语句块, 执行子类构造器中的其他代码, 一个对象被创建.
package selfimpr.test; public class TestDynamicLocked { /** * @param args */ public static void main(String[] args) { new Child(); } }
父类:
package selfimpr.test; public class Parent { public static int a = 1; static { a = 2; p1(); } public int b = 3; { b = 4; p1(); p2(); } public Parent(int a) { } public static void p1() { System.err.println("Parent-a: " + a); } public void p2() { System.err.println("Parent-a: " + a); System.err.println("Parent-b: " + b); } }
子类:
package selfimpr.test; public class Child extends Parent { public static int a = 11; static { a = 21; p1(); } public Child() { //由于Parent没有无参构造器,所以必须显示调用一次父类构造器. //以便Child的对象持有super引用. super(a); //调用此方法时,访问的是父类中的a,此时不能访问Child中的a. } public Child(int arg1) { //每个构造器都必须能够让编译器知道通过该构造器可以让Child对象持有super引用. //并且调用父类构造器的那一句必须是第一句. //例如this();进入Child的无参构造器,Child的无参构造器的第一句是super(a); // this(); super(arg1); } public int b = 31; { b = 41; p1(); p2(); } public static void p1() { System.err.println("Child-a: " + a); } public void p2() { System.err.println("Child-a: " + a); System.err.println("Child-b: " + b); } }
内存分析:
1. 进入ClassLoader的loadClassInternal(String name)方法,加载Child类.
2. 同1,加载Parent类.
3. 初始化Parent的静态成员变量.Parent.a=1;
4. 调用Parent的静态代码块.Parent.a=2;执行方法p1();此时,调用的p1方法是Parent类的.所以输出Parent-a: 2.实际调用了Parent.p1(Parent.a);
5. 初始化Child的静态成员变量.Child.a=11;
6. 调用Child的静态代码块.Child.a=21;执行方法p1();此时调用的p1方法是Child类的.所以输出Child-a: 21.实际调用了Child.p1(Child.a);
7. 此时,类的加载,以及静态成员变量,静态语句块执行完毕.
8. 下面才真正开始进入new Child();
9. 首先进入的当然是Child的无参构造器中的super(a);这一句.
10. 进入Parent的Parent(int a)这个构造器.
11. 这个构造器其实是有隐式的super();这一句的.他是去调用了java.lang.Object的无参构造器,再向里,就是JVM的内幕了,我们就不参与了.
12. 调用完父类的构造器之后,下一步工作就是初始化成员变量.因此Parent的成员变量b=3执行.
13. 执行Child的动态语句块.b=4的赋值自然是Parent对象的成员变量b=4;一定注意,此时Child的成员变量b=0;调用p1()方法,由于是静态的,所以输出Parent自己的东西.调用p2()方法的时候,动态方法被重写,多态存在,所以这里输出的Child-b: 0,很明显,这里调用了子类的方法(p2);
14. 动态语句块执行完,就该执行Parent的构造器中super()之后的语句了.这里要注意,虽然Parent(int a)这个构造器中没有代码,但隐式的有一个super();由于后面再没有代码,所以Parent(int a)这个构造器就算执行完毕了,下面进入子类Child的构造器.
15. 当然,还是成员变量的初始化,b=31.
16. 然后,执行动态语句块,b=41.
17. 调用p1方法,是Child的p1方法.所以输出Child-a: 21;
18. 进入p2方法,调用的方法是Child的p2()方法,此时Child的成员变量b=41,当然输出的是Child-b:41;
19. 当这些过程全部执行完毕之后,整个构造器就算执行完毕了.
看看上面这些过程,new一个对象需要耗费多少的精力?
让我们看一看顺序:
加载子类, 加载父类, 初始化父类静态成员变量, 执行父类静态语句块, 初始化子类静态成员变量, 执行子类静态语句块, 调用子类的构造器, 调用父类的构造器, 初始化父类的成员变量, 执行父类的动态语句块, 执行父类构造器中的其他代码, 初始化子类的成员变量, 执行子类的动态语句块, 执行子类构造器中的其他代码, 一个对象被创建.
相关文章推荐
- Java程序内存分析:jdk自带的jmap能为我们带来什么
- Java程序内存分析:jdk自带的jmap能为我们带来什么
- Java的内存模型分析
- java 内存泄露分析工具-mat
- 问题分析-无界线程池误用导致OOM:java.lang.OutOfMemoryError:unable to create new native thread
- Java---线程多(工作内存)和内存模型(主内存)分析
- java学习笔记-java jvm内存结构分析
- 菜鸟学Java(二十三)——Java内存分析
- java 对象转型内存分析
- Java内存原型分析:基本知识
- java内存分析(转载)
- Java内存机制和是否会有内存泄漏什么情况下会泄漏
- Java的内存分析
- Java HashMap 分析之四:查找和内存使用
- java学习笔记_内存分析
- Java报表FineReport在医院院长查询分析系统中有什么用
- Java数组(Array)_基本概念_内存分析
- java.lang.OutOfMemoryError: unable to create new native thread无法创建本地线程分析
- java内存分析 栈 堆 常量池的区别
- 浅谈java内存分析