Java &引用;“泄漏此信息”;从设计的角度来看

Java &引用;“泄漏此信息”;从设计的角度来看,java,constructor,logic,this,Java,Constructor,Logic,This,警告:在构造函数中泄漏“this” 我不断遇到这种情况,我有一种烦躁的感觉,那是因为我的设计是错误的或不是最优的 我知道此警告提醒我允许访问可能未完全初始化的对象 假设我需要一个有并且需要列表的框架(框架(列表))。在列表中,我可能要执行一些操作,例如add()。为了确保框架尽可能少地了解列表(只知道它有一个),我想从列表中访问包含框架(列表有一个框架?)。这似乎有点傻,但我有2+个列表实现,它们将以不同的方式使用框架 为了确保正确使用我的代码,我需要在List的构造函数中使用一个框架。 我还需

警告:在构造函数中泄漏“this”

我不断遇到这种情况,我有一种烦躁的感觉,那是因为我的设计是错误的或不是最优的

我知道此警告提醒我允许访问可能未完全初始化的对象

假设我需要一个有并且需要列表的框架(框架(列表))。在列表中,我可能要执行一些操作,例如add()。为了确保框架尽可能少地了解列表(只知道它有一个),我想从列表中访问包含框架(列表有一个框架?)。这似乎有点傻,但我有2+个列表实现,它们将以不同的方式使用框架

为了确保正确使用我的代码,我需要在List的构造函数中使用一个框架。 我还需要在Frame的构造函数中列出一个列表,因为它必须有一个:

public abstract class Frame {
    private final List list;

    public Frame(List list) {
        this.list = list;
        list.setFrame(this);
    }
}

public abstract class List {
    private Frame frame;

    protected final void setFrame(Frame frame) {
        this.frame = frame;
    }
}
那么,这是一个糟糕的设计,还是我真的应该创建一些中间脚手架来实现这一点,或者甚至将脚手架留给用户


谢谢

介绍一种工厂方法:

public static Frame createFrame(List list) {
    Frame frame = new Frame(list);
    list.setFrame(frame);
}

private Frame(List list) {
    this.list = list;
}
这不会泄露这一点,并且始终确保所有内容都正确配置,而不需要每个调用方都记住初始化关联的两侧。

我认为这种“双链接”结构,其中一个帧指向指向其父帧的列表,这是你应该避免的,除非你有特别的需要。如果可能,您应该尝试将两个对象中的一个作为指向“子对象”的“父对象”

一开始有点难以理解为什么双重链接不是一个好主意,但以下是一些原因:

  • 在具有明确父子关系的结构中,在多个父对象中重用相同的子对象很简单。另一方面,在双链接结构中,如果要创建一个新结构以共享原始结构中的某些元素,则必须创建感兴趣元素的新副本,或者必须销毁原始结构
  • 有许多设计模式依赖于对象图中清晰的“命令”链,而双链接结构使代码读者看不到该命令链
  • 在很多情况下,处理子级需要了解子级出现的父级,通过将父级作为“上下文”参数传递给处理子级的方法,可以更好地处理这些情况。这种模式的经典示例是在解释器中,表达式的求值将包含求值子表达式所需的所有外部信息的“环境”作为参数。(或者,您可以使用有状态迭代器或分层访问者来导航结构并跟踪位置。)

  • 这并不是说双链接结构永远都不合适,而是说更简单的单链接结构应该是首选。

    我很困惑,如果框架是这样创建的,我该如何扩展它?保护基本框架构造函数,并且在子类中提供一个类似的工厂方法。那么框架实例在List类中究竟将如何使用呢?在绝大多数情况下,除非你非常聪明和细致,否则构造函数不应该调用可重写的方法。高效Java的Josh Block甚至说“构造函数不能调用可重写的方法”。而且他比大多数人都聪明。@user949300好吧,假设方法调用是最终的。无论如何都需要这样做,因为方法以特定的方式工作是很重要的