假设我有以下代码:
public class Conf{
public Conf(String szPath) throws IOException, ConfErrorException{
...
}
public void someMethod(){
...
}
}
然后我想以这种方式实例化对象:
Conf configuration = new Conf("/etc/myapp/myconf.conf");
如果由于某种原因,构造函数抛出任何定义的异常,是否会创建对象?我的意思是,我是否仍然可以访问其中的方法,例如,如下所示码?
Conf configuration;
try{
configuration = new Conf("/etc/myapp/myconf.conf");
}catch(IOException|ConfErrorException e){
//Suppose we entered here
configuration.someMethod();
}
答案 0 :(得分:5)
构造函数抛出任何定义的异常,是否会创建对象?
始终在调用构造函数之前创建对象。否则,构造函数中将没有this
对象进行初始化。
如果你抛出一个Exception,你将失去对该对象的引用,除非你做了一些可疑的事情,比如在抛出异常之前将对象存储在构造函数中。
public class Main {
static class ThrowsException {
static final List<ThrowsException> BAD_LIST = new ArrayList<>();
ThrowsException() {
System.out.println("this = " + this);
BAD_LIST.add(this);
throw new RuntimeException();
}
}
public static void main(String... args) {
for (int i = 0; i < 3; i++) {
ThrowsException te = null;
try {
te = new ThrowsException();
} catch (Exception ignored) {
}
System.out.println("te = " + te);
}
System.out.println(ThrowsException.BAD_LIST);
}
打印
this = Main$ThrowsException@22911fb5
te = null
this = Main$ThrowsException@65b8b5cd
te = null
this = Main$ThrowsException@41a7d9e7
te = null
[Main$ThrowsException@22911fb5, Main$ThrowsException@65b8b5cd, Main$ThrowsException@41a7d9e7]
答案 1 :(得分:5)
让我先从一个失败的对象构造开始,这个场景可以说明如果你可以使用这样的失败对象会出现什么问题:
让我们定义一个A类,以便:
class A {
private String a = "A";
public A() throws Exception {
throw new Exception();
}
}
现在,我们假设我们想在try...catch
块中创建一个类型为A的对象。
A a = null;
try{
a = new A();
}catch(Exception e) {
//...
}
System.out.println(a);
显然,此代码的输出将为:null
。
为什么Java不返回部分构造的A版本?毕竟,在构造函数失败的情况下,name
字段成员已经初始化了,对吗?
Java没有这样做,因为该对象未成功构建。该对象处于不一致状态,因此被Java丢弃。您的变量A甚至没有初始化,它保持为null。
现在,正如您所知,要完全构建新对象,必须首先初始化其所有超类。如果其中一个超类无法构建,那么对象的最终状态是什么?无法确定这一点。
看看这个更详细的例子
class A {
private final int a;
public A() throws Exception {
a = 10;
}
}
class B extends A {
private final int b;
public B() throws Exception {
methodThatThrowsException();
b = 20;
}
}
class C extends B {
public C() throws Exception { super(); }
}
当调用C
的构造函数时,如果在初始化B
时发生异常,那么最终变量int b
的值是多少?
因此,无法创建对象C,它是虚假的,它是垃圾,它没有完全初始化。
答案 2 :(得分:2)
Conf configuration = new Conf("/etc/myapp/myconf.conf");
此代码分三步完成:
configuration
由于您不已完成第二步,第二步也不会完成,这意味着configuration
将不会被初始化。这意味着configuration
不是 null,甚至没有初始化。您的代码将无法编译。
然而,由于第一步完成,会有一堆丢失的物品(符合GC条件)。
答案 3 :(得分:2)
不,构造函数抛出异常会突然完成try块。构造函数没有返回任何内容。块中没有更多内容。这意味着,在您的代码中,配置保持不变。
答案 4 :(得分:1)
将创建一个对象但您永远不会收到对它的引用。就目前而言,您的代码永远不会编译:
Conf configuration;
try{
configuration = new Conf("/etc/myapp/myconf.conf");
}catch(IOException|ConfErrorException e){
//Suppose we entered here
configuration.someMethod();
}
编译器认识到configuration
在到达catch块时可能不会被初始化。
答案 5 :(得分:0)
如果由于某种原因,构造函数抛出任何定义的异常,是否会创建对象?
没有。如果构造函数抛出异常,则引用configuration
将不会赋值。
请参阅:What conditions cause object instantiation to return null?
答案 6 :(得分:0)
不,如果对象的构造函数抛出异常,则不会获取对象的实例。
它是不应该由构造函数创建的单例对象的“最佳”方法之一。
答案 7 :(得分:-1)
不,如果在初始化对象时抛出异常,则不会创建该对象。