Java:传递的替代方案;这";作为构造函数参数,以引用创建对象

Java:传递的替代方案;这";作为构造函数参数,以引用创建对象,java,constructor,this,Java,Constructor,This,我花了一段时间思考不同的解决方案,正如我所读到的(我还没有真正的Java经验),将其用于构造函数参数通常不是一个好的实践 我试图做的是实例化JobGroupMod类的几个对象,对于每个JobGroupMod,我必须创建一定数量的JobMod对象,这些对象必须能够引用它们从中产生的JobGroupMod对象 为了实现这一点,我将“this”传递给JobMod构造函数,但是,即使可以工作,它也感觉不到正确的设计 public class JobGroupMod implements JobGroup

我花了一段时间思考不同的解决方案,正如我所读到的(我还没有真正的Java经验),将其用于构造函数参数通常不是一个好的实践

我试图做的是实例化JobGroupMod类的几个对象,对于每个JobGroupMod,我必须创建一定数量的JobMod对象,这些对象必须能够引用它们从中产生的JobGroupMod对象

为了实现这一点,我将“this”传递给JobMod构造函数,但是,即使可以工作,它也感觉不到正确的设计

public class JobGroupMod implements JobGroup {

    public JobGroupMod(Node n,Set<Job> clusterJobs){
        JobMod j=new JobMod(n,this);
    }
}

我的问题是,有没有更好的方法来解决这个问题,或者我的解决方案是建议的方法?

通常没有魔法。您可以通过构造函数传递参数,也可以稍后使用setter/init方法等初始化参数

如果您的类
JobMod
需要引用
JobGroupMod
,并且与之无关,请使用构造函数传递它。如果有时不使用它,则创建可以初始化此引用的
init()
方法或setter


顺便说一句,有时您必须创建参数化和默认构造函数:首先是为了常规编程使用,其次是如果您使用的是XML、JSON或其他序列化,这对于类似bean的类来说比较容易。在这种情况下,至少要创建javadoc来解释不应该直接使用默认构造函数

只要它仍然是您在
JobGroupMod
构造函数中执行的唯一操作,那么只要您了解其后果,它就相当安全。现实世界中有很多Java代码都可以做到这一点。这仍然不是您真正想要做的事情,特别是当您开始谈论多线程和并发时

危险是在一个物体被完全构造之前把这个传递给另一个物体。如果构造函数在您执行此操作后抛出异常,并且没有完全构造,则可能会出现严重问题。如果另一个线程在完全构造之前访问您传递给它的对象,您将遇到一个严重的问题


在Java中,您经常会发现人们使用工厂模式来避免这种情况,“init”类型的方法或依赖项注入

您应该尝试使用静态工厂方法()

这样可以避免在构造函数调用中传递
This
,至少可以说这是非常不明智的。
示例代码:

public class JobGroupMod implements JobGroup {

    public static JobGroupMod createModeMod(Node n, Set<Job> clusterJobs) {
        JobGroup jg = new JobGroupMod();
        JobMod j = new JobMod(n, jg);
        return jg;
    }
}
公共类JobGroupMod实现JobGroup{
公共静态JobGroupMod createModeMod(节点n,设置群集作业){
JobGroup jg=新的JobGroupMod();
JobMod j=新的JobMod(n,jg);
返回jg;
}
}

@NikolayKuznetsov在问题中添加了一个选项,因为问题很明显。您应该避免将
这个
从构造函数内部传递给另一个方法。对象未完全构造,最终可能会出现难以诊断的严重问题(与可见性和多线程相关)。在多线程环境中,这是一个bug。您正在放弃对非完全构造对象的引用非静态内部类隐式接收对创建它们的周围类的实例的引用。即使这是程序顺序中的最后一件事,也不能保证执行不会对内存操作重新排序,因此在任何位置都是不安全的。(而且,在讨论正确性时,没有什么是相当安全的:程序要么正确,要么不正确;如果规范保证它总是能工作,那么它就是正确的,如果构造函数在任何情况下都无法引用此,则情况并非如此)我认为在现实世界中(可悲的是)有很多类似OPs的代码,但实际上并没有发生。话虽如此,我还是要编辑一下。@BrunoReis:谁说这个类应该是线程安全的?大多数编写的类并非如此,应用于线程安全的所有限制也不一定适用于非线程安全类。我并不是说这样做是个好主意,但如果这个类不是线程安全的类,那也没那么糟糕。你知道它是什么吗?你是否测试过OP使用的确切平台,以了解这个未指定的行为是否对他有利?其他StackOverflow阅读器将使用的确切平台是什么?这是不可能做到的,所以当某件东西明显错误时(即未指明),说它相当安全是非常危险的。@BrunoReis:我不同意。根据这种逻辑,我们应该使每个修改两个字段的方法在我们编写的每个答案中默认同步,以防类被认为是线程安全的。在99%的情况下,我们编写了非线程安全类。我很容易解释,如果类必须是线程安全的,那么从构造函数中转义
this
是绝对不可能的,但是默认情况下假设线程安全要求是不现实的;我实现了你的代码,它马上就工作了。我所做的唯一更改是将CreateModemod方法设置为静态。显然,这一点非常感谢:-)解决了当有人使用反射调用构造函数时出现的问题。工厂方法不再有效。
public class JobGroupMod implements JobGroup {

    public static JobGroupMod createModeMod(Node n, Set<Job> clusterJobs) {
        JobGroup jg = new JobGroupMod();
        JobMod j = new JobMod(n, jg);
        return jg;
    }
}