今天遇到一个问题一直想不明白,求大侠指点。public class Test() {
Test t = null;

Test() {
//
}
}
public class Test() {
Test t = null;

Test() {
t = new Test();
}
}public class Test() {
Test t = null; public static Test getTest() {
if(t == null) {
t = new Test();
}
return mgr;
} private Test() {
//
}
}
我想知道这三种在new一个新Test类时,是怎么工作的,第一种应该没什么问题。那个第二种那样是不是会,一直无限循环下去,一直new Test,因为他构造方法中会new一个新的Test出来,然后,被new出来之前他需要再new一个Test,这样一直循环下去。第三种也没什么问题。

解决方案 »

  1.   

    虽然我没去测试,但是我觉得理论上不可能无限循环,java里面运行机制里面, 不使用该实例化的话一般会不做处理的,应该会终止程序吧
      

  2.   

    那如果是这样的呢public class Test() {
        Test t = null;
        
        Test() {
            t = new Test();
        }
    }
      

  3.   

    不好意思楼上的发错了,如果是这样的呢?public class Test() {
        public static Test t = null;
        
        Test() {
            t = new Test();
        }
    }
      

  4.   

    5楼肯定没问题,4楼也应该没有问题。因为你赋值是null,而不是new Test()。
    但是你的定义行写错了:public class Test() { //没有括号
      

  5.   


    谜题40:不情愿的构造器
    尽管在一个方法声明中看到一个throws子句是很常见的,但是在构造器的声明中看到一个throws子句就很少见了。下面的程序就有这样的一个声明。那么,它将打印出什么呢? 
    public class Reluctant {
        private Reluctant internalInstance = new Reluctant();
        public Reluctant() throws Exception {
            throw new Exception("I'm not coming out");
        }
        public static void main(String[] args) {
            try {
                Reluctant b = new Reluctant();
                System.out.println("Surprise!");
            } catch (Exception ex) {
                System.out.println("I told you so");
            }
        }
    }main方法调用了Reluctant构造器,它将抛出一个异常。你可能期望catch子句能够捕获这个异常,并且打印I told you so。凑近仔细看看这个程序就会发现,Reluctant实例还包含第二个内部实例,它的构造器也会抛出一个异常。无论抛出哪一个异常,看起来main中的catch子句都应该捕获它,因此预测该程序将打印I told you应该是一个安全的赌注。但是当你尝试着去运行它时,就会发现它压根没有去做这类的事情:它抛出了StackOverflowError异常,为什么呢?
    与大多数抛出StackOverflowError异常的程序一样,本程序也包含了一个无限递归。当你调用一个构造器时,实例变量的初始化操作将先于构造器的程序体而运行[JLS 12.5]。在本谜题中, internalInstance变量的初始化操作递归调用了构造器,而该构造器通过再次调用Reluctant构造器而初始化该变量自己的internalInstance域,如此无限递归下去。这些递归调用在构造器程序体获得执行机会之前就会抛出StackOverflowError异常,因为StackOverflowError是Error的子类型而不是Exception的子类型,所以catch子句无法捕获它。 对于一个对象包含与它自己类型相同的实例的情况,并不少见。例如,链接列表节点、树节点和图节点都属于这种情况。你必须非常小心地初始化这样的包含实例,以避免StackOverflowError异常。至于本谜题名义上的题目:声明将抛出异常的构造器,你需要注意,构造器必须声明其实例初始化操作会抛出的所有被检查异常。下面这个展示了常见的“服务提供商”模式的程序,将不能编译,因为它违反了这条规则:
    public class Car {
         private static Class engineClass = ...; 
         private Engine engine = 
                 (Engine)enginClass.newInstance();
         public Car(){ }
    }尽管其构造器没有任何程序体,但是它将抛出两个被检查异常,InstantiationException和IllegalAccessException。它们是Class.Instance抛出的,该方法是在初始化engine域的时候被调用的。订正该程序的最好方式是创建一个私有的、静态的助手方法,它负责计算域的初始值,并恰当地处理异常。在本案中,我们假设选择engineClass所引用的Class对象,保证它是可访问的并且是可实例化的。
    下面的Car版本将可以毫无错误地通过编译:
    //Fixed - instance initializers don’t throw checked exceptions
    public class Car {
         private static Class engineClass = ...;
         private Engine engine = newEngine;
         private static Engine newEngine() {
        try {
              return (Engine)engineClass.newInstance();
           } catch (IllegalAccessException e) {
                     throw new AssertionError(e);
             } catch (InstantiationException e) {
                     throw new AssertionError(e);
             }
         }
         public Car(){ }
    }总之,实例初始化操作是先于构造器的程序体而运行的。实例初始化操作抛出的任何异常都会传播给构造器。如果初始化操作抛出的是被检查异常,那么构造器必须声明也会抛出这些异常,但是应该避免这样做,因为它会造成混乱。最后,对于我们所设计的类,如果其实例包含同样属于这个类的其他实例,那么对这种无限递归要格外当心。
      

  6.   

    会像你说的那样,死循环了,然后造出了很多对象,导致StackOverflowError异常产生。请问楼主为什么要写一段这样的代码,是理解单例模式吗?
      

  7.   

    终于明白过来,如果将类本身放到 constructer 中,他就会不断的调用 init , 所以就产生发生了上面的java.lang.StackOverflowError 溢出错误.
      

  8.   

    楼主的程序能编译通过吗?尤其第三个,public class Test() {
        Test t = null;    public static Test getTest() {
            if(t == null) {
                t = new Test();
            }
            return mgr;
        }    private Test() {
            //
        }
    }mgr是什么东西?
      

  9.   


    不好意思,刚才有点事没在。嗯,是我写错了随手就加了个(),我想问下 4楼的那个t虽然是null但是我在构造方法中给他赋值了,这样执行构造方法是不是会要不停的new下去?5楼的t是static的不管new多少都会是指向同一个对象,但是他还是会不停的new的吧??求解答。