java - 不可变变量的延迟初始化

标签 java constructor immutability

我一直在大量使用 scala 的 lazy val 习惯用法,我想在 Java 中实现类似的功能。我的主要问题是要构造一些值,我需要一些在对象构造时未知的其他值,但我不希望之后能够更改它。这样做的原因是,我正在使用一个 GUI 库,它代表我实例化对象,并在创建我需要的所有内容时调用不同的方法,也就是当我知道我需要的值时。

以下是我尝试实现的属性:
* 我的变量的不变性。
* 在构造函数之外的其他方法中进行初始化。

我认为这在 Java 中是不可能的,因为只有 final 实现了变量的不变性,而 final 变量不能在构造函数之外初始化。

Java 中最接近我想要实现的目标的是什么?

最佳答案

一种方法是将相关值的实际实例化插入另一个类。这将是最终的,但在加载类之前不会实际创建,它会延迟到需要时才创建。类似于以下内容:

public class MyClass
{
    private static class Loader
    {
        public static final INSTANCE = new Foo();
    }

    Foo getInstance()
    {
        return Loader.INSTANCE;
    }
}

这将延迟初始化 Foo在需要的时候。

如果您绝对需要 Foo成为顶级类的实例变量——我想不出任何方法来做到这一点。如您所述,变量必须填充到构造函数中。

事实上,我不确定 Scala 是如何解决这个问题的,但我的猜测是它设置了 lazy val变量为某种 thunk ,在第一次评估时被实际对象替换。在这种情况下,Scala 当然可以通过颠覆正常的访问修饰符来做到这一点,但我认为您不能在 Java 中透明地做到这一点。您可以将该字段声明为例如一个Future<Foo>它在第一次调用时创建值并从那时起缓存它,但这不是引用透明的,并且根据 final 的定义我看不出解决这个问题的方法。

关于java - 不可变变量的延迟初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4134694/

相关文章:

Java 继承 : Reducing visibility in a constructor vs inherited method

c# - ImmutableList 和 List 之间的一般性能比较?

class - 对象中的可变值

单击绘图区域时 Java 背景发生变化

java - 从构造函数抛出未经检查的异常时面临 java.lang.StackOverflowError

java - 如何在点击后退按钮 5 次时显示插页式广告

c++ - Borland C++ 5.02 无法调用带参数的构造函数

java - 我的 traverse 方法不会传递 int 的值,但可以传递 ArrayList 的值

java - JaxRsClient (OkHttpClient) 比 Feign (HttpURLConnection) 或 cURL 慢很多

java - 基于 Eclipse 的 E3 应用程序,切换工作区不起作用