始终在Java中使用构造函数后执行方法

Rik*_*aaf 6 java multithreading constructor

我有一种情况,我总是需要运行一些依赖于对象本身的代码

public abstract class A{
    public A(X x){
        //init A stuff
        x.getAList("stuff").add(this);
        x.getAList("otherstuff").add(this);
    }
}

public class B extends A{
    public B(X x){
        super(x);
        //init B stuff
    }
}

public class C extends A{
    public C(X x){
        super(x);
        //init C stuff
        x.getAList("otherstuff").remove(this);
        x.getAList("morestuff").add(this);
    }
}

public class SomeClass{
    private X someX;

    public A somefunc(boolean b){
        if(b){
            return new B(someX);
        }else{
            return new C(someX);
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

问题如下.在这个例子中,我this在构造函数中使用.如果另一个线程试图通过someX.getAList访问该对象,则可能导致该线程在构造函数结束之前访问该对象.

你可以使它通过somefunc将对象添加到AList中

public class SomeClass{
    private X someX;

    public A somefunc(boolean b){
        A a;
        if(b){
            a = new B(someX);
            someX.getAList("stuff").add(a);
            someX.getAList("otherstuff").add(a);
        }else{
            a = new C(someX);
            someX.getAList("stuff").add(a);
            someX.getAList("morestuff").add(a);
        }
        return a;
    } 
}
Run Code Online (Sandbox Code Playgroud)

问题是B和C也可以在别处实例化,并且每次创建B或C时都需要以指定的方式添加它们.我不希望将对象添加到AList是用户的责任,而是类的责任.我也不希望用户必须调用为它们执行此操作的init函数.另一方面,我不想要任何并发问题.

有没有一种方法或模式可以实现这一点?

Golang有类似defer的东西,它允许你在函数/ method/constructor完成后运行一段代码.

Hop*_*ful 9

为super和subclass创建一个Factory-Method,并使构造函数成为私有,强制每个想要实例的人使用工厂方法.工厂方法是返回完全构造的实例的方法.一旦实例完全构造(在工厂方法中调用构造函数之后)将实例添加到列表中,这样就没有线程可以获得不完整/未完成的实例.

Factory-Method的要点是严格地将所有初始化代码与任何非初始化代码隔离,以避免访问和暴露未初始化的字段.它还可以作为用户的选择器,自动返回合适的(子)类型,而无需指定.(有趣的设计模式)

abstract class A{
    protected A(){
        //constructor code goes here
    }
    public void afterFinalisation(final X x) {
        x.getAList("stuff").add(this);
        x.getAList("otherstuff").add(this);
    }
}

class B extends A{
    protected B(){
        super();
        //constructor code goes here
    }
    public static B create(final X x) {
        final B returnValue = new B();
        returnValue.afterFinalisation(x);
        return returnValue;
    }
}

class C extends A{
    protected C(){
        super();
        //constructor code goes here
    }
    @Override
    public void afterFinalisation(final X x) {
        super.afterFinalisation(x);
        x.getAList("otherstuff").remove(this);
        x.getAList("morestuff").add(this);
    }
    public static C create(final X x) {
        final C returnValue = new C();
        returnValue.afterFinalisation(x);
        return returnValue;
    }
}

class SomeClass{
    private final X someX = new X();

    public A somefunc(final boolean b){
        if(b){
            return B.create(this.someX);
        }else{
            return C.create(this.someX);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

构造函数代码的功劳归功于我的回答的coolcats迭代,我试图避免将代码放入受保护的构造函数中,而是使用init()方法,这需要一个非常不优雅的最终字段的解决方法.