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.
答案是cd.整个程序过程不是太懂,哪位大哥帮忙解释一下  谢谢了!

解决方案 »

  1.   

    makeThings()方法结束后,局部变量test出了作用域
    TestA的对象除了和TestB的对象之间存在循环引用(a是TestA对象的引用,b是TestB对象相的引用)之外,没有来自外部的引用
    这样的情况是有资格被垃圾回收器回收的
      

  2.   

    TestA的对象和TestB的对象之间交叉调用不是一直在makeThings()方法之内吗?test是怎么出作用域的?
    能不能解释一下循环调用的细节过程吗
    谢谢
      

  3.   

    1. class TestA {      //类TestA
    2. TestB b;            //类TestA的成员变量b,是一个TestB类型的
    3. TestA() {                  //类TestA的无参构造函数
    4. b = new TestB(this);         //实例化类TestA时将成员变量b赋值,调用了TestB的构造方法,传入本实例化TestA对象本身.
    5. } 
    6. } 
    7. class TestB {             //类TestB
    8. TestA a;                      //类TestB的成员变量a ,是一个TestA类型的
    9. TestB(TestA a) {               //类TestB的构造函数。参数为TestA类型.
    10. this.a = a;                   //将传入的参数赋值给成员变量a.
    11. } 
    12. } 
    13. class TestAll {                        //TestAll类
    14. public static void main (String args[]) {        //main函数
    15. new TestAll().makeThings();                    //创建一个TestAll匿名对象出来并调用makeThings()方法
    16. // ...code continues on 
    17. } 
    18. void makeThings() {                   //makeThings()方法
    19. TestA test = new TestA();                 //创建一个新的TestA类型变量test.
    20. } 
    21. } 
    //题目意思:在15行之后和main方法结束前,哪两种说法是正确的?
    Which two statements are true after line 15, before main completes? (Choose two) 
    A. Line 15 causes a stack overflow.    //A:15行发生一个堆栈溢出
    B. An exception is thrown at runtime.      //B:会产生一个运行期间异常
    C. The object referenced by a is eligible for garbage collection.    //C: a引用对象成为了垃圾.
    D. The object referenced by b is eligible for garbage collection. //D:  b引用对象成为了垃圾.
    E. The object referenced by a is not eligible for garbage collection.    //E:  a引用对象没有成为垃圾.
    F. The object referenced by b is not eligible for garbage collection.    //F: b引用对象没有成为垃圾.
    分析:
      答案A明显是错误的,虽然类TestA的构造函数里new了一个类TestB,但在类TestB的构造函数中,只是将传入的TestA类对象赋值给自己的成员变量b.所有并没有产生循环调用,也就不会产生内存溢出.
      答案B也是错的,理由同答案A差不多.
      答案C和D是正确的,第15行在new出一个TestAll匿名对象后,调用了makeThings()方法.先不看这个方法.我们知道匿名对象只是拿来用用,就象厕纸一样,用了就丢了,所以第16行时候,这个没有名字的TestAll对象将会成为垃圾(用题目的话来说就是符合垃圾收集的标准).然后我们再来看他调用的这个makeThings()方法,这个方法虽然new了一个有名字的对象,但是很遗憾,他在超出方法代码后,也成为了垃圾.那么他所产生的a对象和b对象都成为了垃圾.
      答案E和F是也是错的。
      

  4.   

    谢谢!
    “但在类TestB的构造函数中,只是将传入的TestA类对象赋值给自己的成员变量b.所有并没有产生循环调用”
    对这句话不理解  成员变量b应该是成员变量a吧?
    另外,如何修改才能使之产生循环调用呢?
      

  5.   

    类TestB的成员变量a和类TestA的成员变量b没有任何关系.
    如下修改成循环调用:
    class TestB { 
    8. TestA a; 
    9. TestB(TestA a) { 
    10. this.a = new TestA();
    11. } 
    12. } 
      

  6.   

    1. TestB的对象和TestA的对象构成了循环引用,又不是循环调用,只不过是建立了一个TestA的对象,一个TestB的对象,各自的成员变量引用了对方。不会无限执行下去。
    2. makeThings() 方法执行完了test自然会出作用域。