询问一道关于垃圾回收的题

yjjbmk0113 2004-10-14 10:35:53
1. class TestA {
2. TestB b;
3. TestA() {
4. b = new TestB(this);
5. }
6. }
7. class TestB {
8. TestA a;
9. TestB(TestA a) {
10. this.a = a;
11. }
12. }
13. class TestAll {
14. public static void main (String args[]) {
15. new TestAll().makeThings();
16. // ...code continues on
17. }
18. void makeThings() {
19. TestA test = new TestA();
20. }
21. }
Which two statements are true after line 15, before main completes? (Choose two)
A. Line 15 causes a stack overflow.
B. An exception is thrown at runtime.
C. The object referenced by a is eligible for garbage collection.
D. The object referenced by b is eligible for garbage collection.
E. The object referenced by a is not eligible for garbage collection.
F. The object referenced by b is not eligible for garbage collection.
答案:C D
请问,为什么选CD??
在第4行类TestA的构造方法中调用了TestB的构造方法,其中,TestB构造方法中的参数this是指什么?
在这个程序中TestA的构造方法调用了TestB的构造方法,而TestB的构造方法又调用了TestA的构造方法,这样能运行吗??我调试了一下,结果能够运行!这是为何?请高人指点啊!!!多谢。
...全文
121 7 打赏 收藏 举报
写回复
7 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
xiaorai 2004-11-01
  • 打赏
  • 举报
回复
例子程序:

class TestA {
TestB b;
String strA = null;
TestA() {
System.out.println("TestA.this -> " + this);
System.out.println("TestA.b -> " + b);
b = new TestB(this);
System.out.println("TestA.b -> " + b);
System.out.println("b.strB -> " + b.strB);
strA = "String TestA.";
}
}

class TestB {
TestA a;
String strB = null;
TestB(TestA a) {
System.out.println("TestB.this -> " + this);
System.out.println("a -> " + a);
System.out.println("a.strA -> " + a.strA);
this.a = a;
System.out.println("TestB.a -> " + this.a);
System.out.println("TestB.a.b -> " + this.a.b);
System.out.println("TestB.a.strA -> " + this.a.strA);
strB = "String TestB.";
}
}

class TestAll {
public static void main (String args[]) {
TestAll t = new TestAll();
TestA ta = t.makeThings();
// ...code continues on
System.out.println("ta.b -> " + ta.b);
System.out.println("ta.strA -> " + ta.strA);
System.out.println("ta.b.strB -> " + ta.b.strB);
System.out.println("ta.b.a -> " + ta.b.a);
System.out.println("ta.b.a.strA -> " + ta.b.a.strA);
}

/*
void makeThings() {
TestA test = new TestA();
System.out.println("test.b -> " + test.b);
System.out.println("test.b.a -> " + test.b.a);
}
*/

TestA makeThings() {
TestA test = new TestA();
return test;
}

}


输出结果:
C:\Ebooks\SCJP\MySCJP>java TestAll
TestA.this -> TestA@131f71a
TestA.b -> null
TestB.this -> TestB@197d257
a -> TestA@131f71a
a.strA -> null
TestB.a -> TestA@131f71a
TestB.a.b -> null
TestB.a.strA -> null
TestA.b -> TestB@197d257
b.strB -> String TestB.
ta.b -> TestB@197d257
ta.strA -> String TestA.
ta.b.strB -> String TestB.
ta.b.a -> TestA@131f71a
ta.b.a.strA -> String TestA.


从中可以得出下面几个结论(当然,与本题目无关):
1 New一个类的时候其实在进入构造函数之前这个类的地址空间已被分配好。
2 此时这个没有完整构造的类的所有公开属性变量都可以被调用,不会出错。但是由于大多变量并未完成初始赋值,调用的结果是空值。
3 在构造函数执行完毕之后,所有的公开属性变量都被设定了初始值,这时候如果使用在第2步中保存了的此类的引用来调用公开属性变量,将会得到正确的结果。






xiaorai 2004-11-01
  • 打赏
  • 举报
回复
有意思的课题。做了一番验证,结论如下。

就本题目而言,最快,最简单的解决办法,正如 fjalan(fjalan) 所言,void makeThings() 方法不返回任何的值,test 在这个方法里面只是个局部变量而已,不管这个局部变量在赋值的过程中产生了多么翻江倒海的操作,在方法结束的时候,它只能成为一个等待回收的垃圾。自然,被包在这个垃圾中的a和b,也只不过是大垃圾中的小垃圾。所以C和D是正确的。


接下来我验证了那些“翻江倒海”的操作,也很有趣,请看扩展后的例程和输出结果:


(由于字数太多,转下贴-〉)

qlampskyface 2004-10-27
  • 打赏
  • 举报
回复
http://www-900.ibm.com/developerWorks/cn/java/l-JavaMemoryLeak/index.shtml
city0710 2004-10-14
  • 打赏
  • 举报
回复
你所说的THIS是指调用当前类的对象引数
对于构造方法的调用,其实是个兜圈子,也就是转来转去还是回到了起点,只是绕了个道,这也算是迷惑答题者吧!考试就这样,不是按照常规!至于为什么选CD,楼主还是多看看THINKING IN JAVA吧!没什么好讲的,里面很详细!
rosen 2004-10-14
  • 打赏
  • 举报
回复
解释起来比较复杂。
有文字功底好的来所说吧
yjjbmk 2004-10-14
  • 打赏
  • 举报
回复
关注中ing..........
樟树林的世界 2004-10-14
  • 打赏
  • 举报
回复
TestA test = new TestA();


test 消亡了。 A和B之间的互相引用也消亡了
相关推荐
发帖
Java

4.9w+

社区成员

Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
帖子事件
创建了帖子
2004-10-14 10:35
社区公告
暂无公告