我们说我有以下课程
public class A {
private B b;
}
现在有一个用于创建B实例的工厂,但创建者方法会抛出异常
public class BCreatorFactory {
public static createB() throws SomeException {
// DO the intialization
// ...
return b;
}
如果我在声明行中设置了A.b,那么我将无法处理异常
public class A {
private B b = BCreatorFactory.createB() // BAD -> no way of dealing with the exception
}
如果我在构造函数中设置了A.b,那么我要么有一个“半烘焙”实例,要么再次抛出异常并强制调用代码处理未正确初始化的实例
public class A {
private B b;
public A() {
try {
b = BCreatorFactory.createB();
}
catch (SomeException se) {
// Do something, perhaps try to recover ? <- IMO also BAD
}
}
}
或
public class A {
private B b;
public A() throws SomeException { // BAD
b = BCreatorFactory.createB();
}
}
我可以尝试延迟init B的实例:
public class A {
private B b;
public B getB() throws SomeException {
if (b == null) {
b = BCreatorFactory.createB(); // BAD -> not thread safe -> can result in redundant createB() invocations
}
return b;
}
}
但是我能想到使其线程安全的唯一方法是通过 已知在java的JVM中被破坏 双重检查锁定
public class A {
private B b;
public B getB() throws SomeException {
if (b == null) {
synchronized(this) {
if (b == null) {
b = BCreatorFactory.createB(); // BAD -> not really thread safe -> broken
}
}
}
return b;
}
}
那么,亲爱的患者读者,我应该做什么?
换句话说,初始化包含对创建对象的引用的对象实例的最佳解决方案是什么?
答案 0 :(得分:3)
这有什么问题?
public class A {
private B b;
public A() throws SomeException { // BAD -- *no it's not*
b = BCreatorFactory.createB();
}
}
构造函数抛出异常没有错。
答案 1 :(得分:0)
构造函数抛出异常没有任何问题。 Java框架中的许多类都会从构造函数中抛出异常。只要您有自动处理和解决情况的方法,它也可以在构造函数中捕获异常。在Java中检查异常的要点是,你不能忽略错误条件,你必须在某处处理它。
我抛出异常并强制调用代码来处理未正确初始化的实例
调用代码不必处理不正确初始化的实例,它将自动转到catch块,在那里你应该对异常做一些事情,无论是抛出它,记录它,失败等等。