java - 在 Java 中总是在构造函数之后执行方法

标签 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);
        }
    } 
}

问题如下。在此示例中,我在构造函数中使用了 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;
    } 
}

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

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

Golang 有类似 defer 的东西,可以让你在函数/方法/构造函数完成后运行一段代码。

最佳答案

改为为父类(super class)和子类创建一个工厂方法,并将构造函数设为私有(private),迫使每个想要实例的人都使用工厂方法。工厂方法是一种返回完全构造的实例的方法。一旦实例完全构建(在工厂方法中调用构造函数之后),将实例添加到列表中,这样就没有线程可以获取不完整/未完成的实例。

工厂方法的要点是将所有初始化代码与任何非初始化代码严格隔离,以避免访问和暴露未初始化的字段。它还可以作为用户的选择器,自动返回合适的(子)类型,无需指定。( Interesting design-patterns )

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);
        }
    }
}

构造函数代码归功于 coolcats iteration of my answer ,我试图避免将代码放入 protected 构造函数中,而是使用 init() 方法,这需要对最终字段进行大量不优雅的解决方法。

关于java - 在 Java 中总是在构造函数之后执行方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37380704/

相关文章:

java - 有没有办法在 Java 中生成 8.3 或 'short' (Windows) 版本的文件名?

c# - 在线程中调用UI应用程序

java - 如何在Java中的多个线程之间共享公共(public)日志文件

c++ - 复制构造函数和默认构造函数

c++ - 何时在构造函数中使用 {} ()

java - 如何在显示 android 后更改自定义对话框中 View 的可见性

java - 哪些类型的 REST 服务适用于 Android

java - 无法找出构造函数错误

java - 调用 SOAP 方法 JAX-WS

python - 从脚本运行服务器后 Tkinter 窗口卡住