Java 在构造函数结束后调用方法
我需要在构造函数结束后调用一个方法,我不知道该怎么做。 我有这门课:Java 在构造函数结束后调用方法,java,Java,我需要在构造函数结束后调用一个方法,我不知道该怎么做。 我有这门课: Class A { public A() { //... } public void init() { //Call after the constructor } } 您必须在客户端执行此操作,因此: A a = new A(); a.init(); 或者您必须在构造函数末尾执行此操作: class A { public A() {
Class A {
public A() {
//...
}
public void init() {
//Call after the constructor
}
}
您必须在客户端执行此操作,因此:
A a = new A();
a.init();
或者您必须在构造函数末尾执行此操作:
class A {
public A() {
// ...
init();
}
public final void init() {
// ...
}
}
但是,不建议使用第二种方法,除非将该方法设置为私有或最终方法
另一种选择是使用工厂方法:
class A {
private A() { // private to make sure one has to go through factory method
// ...
}
public final void init() {
// ...
}
public static A create() {
A a = new A();
a.init();
return a;
}
}
相关问题:
- 为什么不这样做:
Class A {
public A() {
//... Do you thing
this.init();
}
public void init() {
//Call after the constructor
}
}
这个怎么样:
Class A {
public A() {
// to do
init();
}
public void init() {
//Call after the constructor
}
}
到目前为止你做了什么?你看起来像这样吗
Class A {
public A() {
//...
}
public void init() {
//Call after the constructor
}
}
public static void main(String[] args)
{
A a = new A();
a.init();
}
您需要一个静态工厂方法来构造对象,调用init方法,最后返回对象:
class A {
private A() {
//...
}
private void init() {
//Call after the constructor
}
public static A create() {
A a = new A();
a.init();
return a;
}
}
请注意,我已将构造函数和
init()
方法设置为私有,因此它们只能由工厂方法访问。客户端代码将通过调用A.create()
而不是调用构造函数来创建对象。我收集了一些想法,并提供了一个可抽象的解决方案:
class A {
protected A() {
// ...
}
protected void init() {
// ...
}
public static <T extends A> T create(Class<T> type) {
try {
T obj = type.newInstance();
obj.init();
return obj;
} catch (ReflectiveOperationException ex) {
System.err.println("No default constructor available.");
assert false;
return null;
}
}
}
A类{
保护A(){
// ...
}
受保护的void init(){
// ...
}
公共静态T创建(类类型){
试一试{
T obj=type.newInstance();
obj.init();
返回obj;
}捕捉(反射操作例外){
System.err.println(“没有可用的默认构造函数”);
断言错误;
返回null;
}
}
}
如果要在构造函数之前调用方法,可以使用初始值设定项块
如果
init()
启动一个新线程或将其此
引用与另一个可能从另一个线程访问该引用的类共享,则不应在构造函数中调用它。如果你这样做,你将有一个数据竞赛。如果你直接在构造函数中这样做,同样的问题也会出现。如果将部分构造委托给init
方法,则没有区别。问题是当init
方法可能被子类重写时。如果使用静态工厂方法,您可能也希望将init
方法设置为私有。如果问题是与其他线程共享此
引用,则会产生不同,因为一旦构造函数完成,类的不变量可能会得到保证,特别是任何最终字段都会保证在其他线程中可见。@aioobe事实上,它的内联也有这个bug,这不会影响我的评论,imhoinit()
方法通常发布this
或派生线程——这就是为什么它们是独立的方法,而不仅仅是在构造函数中。鉴于construct than init模式与init does thread内容有着相对较高的相关性,我认为明确指出这种危险是有帮助的。那么,我想我们在我的评论的相关性上不会有一致的看法。因此,我将把它作为一个注释留给OP:如果您的init()
方法将this
暴露给任何人(另一个线程、另一个类等),那么您将暴露于微妙的数据争用错误中。这样做的风险自负。有些答案似乎是假设init可以简单地在构造函数中移动,但我假设它所做的任何事情都不适合在构造函数中进行(例如注册侦听器,这样就有机会看到部分构造的对象),否则就没有必要问这个问题了。好主意,但如果这些东西是私人的,你就不需要工厂了。您只需在构造函数末尾调用它。但是,如果方法和构造函数受到保护,您可以使用工厂作为一个好的解决方案,以确保重写构造函数不会导致缺少init()调用。当然,如果构造函数是受保护的,并且类是可抽象的,那么您需要一个更通用的工厂方法-忘了提到它了。@UniversE不,您不能简单地在构造函数末尾调用它。Java特别保证构造函数完成后最终字段的可见性。如果将对该对象的引用传递给另一个线程,它可能会看到这些字段的默认值,这在构造函数完成后不会发生。但是如果在构造函数末尾调用它,该方法将在同一线程上执行,并且不会出现可见性问题。@aioobe如果在构造函数末尾调用它,而init()
允许引用此
转义,另一个线程可以在构造函数完成之前检查对象。请参阅yshavit对这个问题的另一个答案的评论。让this
在对象完全初始化之前逃逸是一个糟糕的想法,不管它是从构造函数还是从init方法完成的,也不管是否有多个线程。据我所知,这是处理继承的唯一答案。还是我错了?在这种情况下,构造函数是不完整的。构造函数在运行此.init()之后完成。一般来说,在自己的构造函数中使用它来运行方法是不好的做法,因为构造函数没有完全创建。通常,当你有多个线程时,这会把事情搞砸。@GeorgeXavier你是对的,谢谢你指出这一点。编辑了答案,所以现在这是显而易见的。
class A {
{
init()
}
public A() {
//todo
}
private final void init() {
//todo
}
}