new的后面做了什么?new 干了至少14件事--Java极限内存分析2

Java构造器与多态详解
本文详细解析了Java中父类与子类构造器的执行顺序,以及静态与动态方法在不同上下文中的表现。重点介绍了如何正确使用super关键字,并展示了多态性的具体体现。

主程序:

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一个对象需要耗费多少的精力?
让我们看一看顺序:
加载子类, 加载父类, 初始化父类静态成员变量, 执行父类静态语句块, 初始化子类静态成员变量, 执行子类静态语句块, 调用子类的构造器, 调用父类的构造器, 初始化父类的成员变量, 执行父类的动态语句块, 执行父类构造器中的其他代码, 初始化子类的成员变量, 执行子类的动态语句块, 执行子类构造器中的其他代码, 一个对象被创建.

### 关于天梯赛 L1-067 洛希极限问题的 Java 实现与解题思路 #### 题目理解 题目描述了洛希极限的概念,即一个天体自身的引力与其受到另一个天体引起的潮汐力相等时的距离。当两者的距离小于该极限值时,较小的天体会瓦解并可能形成较大的天体周围的环结构。 对于编程实现而言,重点在于通过给定的数据来判断两个星球之间的关系是否满足特定条下的洛希极限情况[^1]。 #### 数据输入处理 程序首先读取一系列测试案例的数量 `T` ,之后依次接收每一对星体的信息,包括它们的质量比例因子以及半径比率等因素。这些参数用于后续计算洛希极限的具体数值。 #### 计算方法解析 根据物理公式,可以得知洛希极限 \(d\) 的表达式如下: \[ d = 2.44R\left(\frac{\rho_M}{\rho_m}\right)^{1/3} \] 其中: - \( R \) 表示较大质量物体的平均半径; - \( \rho_M / \rho_m \) 是指两者密度之比; 由于本题简化设定为球形均匀分布,则可进一步转换成基于质量和体积的关系来进行估算。具体到代码层面,就是利用已知的比例系数完成相应的运算逻辑。 #### 结果判定输出 最后依据求得的结果对比实际间距,从而得出结论——如果当前距离低于理论上的洛希界限则输出"Yes"表示会发生分裂现象;反之则给出"No"。 ```java import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int T = Integer.parseInt(scanner.nextLine()); while (T-- > 0){ String[] parts = scanner.nextLine().split(" "); double massRatio = Double.parseDouble(parts[0]); double radiusRatio = Double.parseDouble(parts[1]); // Simplified Roche Limit formula calculation based on given ratio values. final double ROCHE_CONSTANT = 2.44; double rocheLimit = ROCHE_CONSTANT * Math.pow(massRatio, 1./3.) * radiusRatio; System.out.println(rocheLimit >= 1 ? "No":"Yes"); } scanner.close(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值