如何初始化需要复杂计算的最终变量?

How to initialise a final variable that requires complex computation?

我是 Java 的初学者。我想知道,如果一个变量在初始化之前需要复杂的计算,但是一旦初始化,它将 not 改变,该怎么办。我想使变量成为最终变量,但与其在构造函​​数中初始化它,不如在方法中初始化它,以便以后可以重用该方法。有什么办法可以做到这一点?

除了上述所有要求之外,如果我只想在需要时计算此变量的值(因为计算它的计算成本很高),会发生什么情况。遇到这种情况怎么办?

不幸的是,您不能在任何给定时刻使变量成为最终变量。如果变量是 final,它可以(并且必须)在构造函数。

您也可以这样做(以下代码归功于 npinti):

private boolean isMutable;
private String someString;

public void setMutable(boolean value)
{
    this.isMutable = value;
}

public void setSomeString(String value)
{
    if (this.isMutable)
    {
        this.someString = value;
    }
}

您可以尝试来自 Guava 的 memoize 供应商:

Supplier<T> something = Suppliers.memoize(new Supplier<T>() {
    // heavy computation
    return result.
});

something.get();
something.get(); // second call will return the memoized object.

看来您需要延迟初始化。当由于某种原因认为结果昂贵时,使用 use 是一种性能优化。目标是 延迟昂贵的计算,直到有必要,并且 存储该昂贵计算的结果,这样计算就不需要再次重复。

示例如下:

public final class Foo {
    private Data data = null; 

    private Data expensiveComputation() {
        if(data == null) { // first call to this method
            Data data = new Data();
            // complex computation
            // store the result to data
        } else {
            return data;
        }
    }
}

如您所见,data 仅在需要时才进行初始化。

请注意,如果您的代码在多线程环境中工作,将会出现问题。这是因为多个线程可以同时调用该方法。为了防止这种情况,我们可以使用 synchronized 关键字:

public final class Foo {
    private volatile Data data = null; 

    private Data expensiveComputation() {
        if(data == null) { // first call to this method
            synchronized(Foo.class) {
                if(data == null) {
                    Data data = new Data();
                    // complex computation
                    // store the result to data
                }
            }
        } else {
            return data;
        }
    }
}

synchronized关键字只允许一个线程可以进入并初始化data