假设我有以下代码:
public class Conf{
public Conf(String szPath) throws IOException, ConfErrorException{
...
}
public void someMethod(){
...
}
}
Run Code Online (Sandbox Code Playgroud)
然后我想以这种方式实例化对象:
Conf configuration = new Conf("/etc/myapp/myconf.conf");
Run Code Online (Sandbox Code Playgroud)
如果由于某种原因,构造函数抛出任何定义的异常,那么是否会创建对象?
我的意思是,我仍然可以访问其中的方法,例如,如下面的代码?
Conf configuration;
try{
configuration = new Conf("/etc/myapp/myconf.conf");
}catch(IOException|ConfErrorException e){
//Suppose we entered here
configuration.someMethod();
}
Run Code Online (Sandbox Code Playgroud)
构造函数抛出任何定义的异常,是否会创建对象?
始终在调用构造函数之前创建对象.否则this,构造函数中将没有对象进行初始化.
如果抛出异常,则会丢失对该对象的引用,除非您在抛出异常之前做了一些可疑的事情,比如将对象存储在构造函数中.
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);
}
Run Code Online (Sandbox Code Playgroud)
版画
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]
Run Code Online (Sandbox Code Playgroud)
让我从一个失败的对象构造的场景开始,这个场景可以举例说明如果你可以使用这样的失败对象会出现什么问题:
让我们定义一个A类,这样:
class A {
private String a = "A";
public A() throws Exception {
throw new Exception();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,让我们假设我们想在try...catch块中创建一个类型为A的对象.
A a = null;
try{
a = new A();
}catch(Exception e) {
//...
}
System.out.println(a);
Run Code Online (Sandbox Code Playgroud)
显然,此代码的输出将是: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(); }
}
Run Code Online (Sandbox Code Playgroud)
当C调用构造函数时,如果初始化时发生异常B,那么最终变量的值是int b多少?
因此,对象C无法创建,它是虚假的,它是垃圾,它没有完全初始化.
| 归档时间: |
|
| 查看次数: |
3596 次 |
| 最近记录: |