唯一的方法是,Whatever 有一个引用 Pilipili 的类变量,并在构造函数的末尾调用它来注册新对象。
public class Blabla {
public static void main(String[] args) {
Whatever.registry = new Pilipili();
Whatever w1 = new Whatever(100, 200, 400);
Whatever w2 = new Whatever(500, 600, 700);
}
}
public class Whatever {
public static Pilipili registry;
private final int alpha, bravo, charlie;
public Whatever(int a, int b, int c) {
this.alpha = a;
this.bravo = b;
this.charlie = c;
if (registry != null) {
registry.register(this);
}
}
}
public class Pilipili {
private int next = 0;
private Whatever[] tabW = new Whatever[20];
public void register(Whatever w) {
tabW[next++] = w;
}
}
但是,这被认为是不安全的。在构造完成之前,Whatever 构造函数不应允许对对象的引用转义。在像这样的简单情况下,这无关紧要,但如果字段是 final 并且对象是从多个线程中使用的,则无法保证所有线程都会看到设置为 final 字段的值。只有在构造函数完成后才能保证。由于其他类能够在构造完成之前看到该对象,因此它可能会看到它处于不一致的状态。
解决这个问题的最好方法是重组你的代码,这样就没有必要了,但下一个最好的方法是使构造函数私有并使用工厂方法创建对象。这样,工厂方法就可以调用构造函数,然后,构造函数完成后,可以将对象注册到监听器或你有什么,然后它可以将构造和注册的对象返回给调用者。
public class Blabla {
public static void main(String[] args) {
Whatever.registry = new Pilipili();
Whatever w1 = Whatever.newInstance(100, 200, 400);
Whatever w2 = Whatever.newInstance(500, 600, 700);
}
}
public class Whatever {
public static Pilipili registry;
private final int alpha, bravo, charlie;
private Whatever(int a, int b, int c) {
this.alpha = a;
this.bravo = b;
this.charlie = c;
}
public static Whatever newInstance(int a, int b, int c) {
Whatever whatever = new Whatever(a, b, c);
if (registry != null) {
registry.register(whatever);
}
return whatever;
}
}
同样,这是安全的,因为当静态工厂方法向 Pilipili 注册实例时,构造函数已经返回。然后,对新建对象的引用可以安全地逃逸到外部世界。