Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何初始化需要复杂计算的最终变量?_Java_Variables_Methods_Constructor_Final - Fatal编程技术网

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

Java 如何初始化需要复杂计算的最终变量?,java,variables,methods,constructor,final,Java,Variables,Methods,Constructor,Final,我是Java的初学者。我想知道,如果一个变量在初始化之前需要复杂的计算,但一旦初始化,它就不会改变,该怎么办。我想将变量设置为final,但与其在构造函数中初始化它,不如在方法中初始化它,以便以后可以重用此方法。有没有办法做到这一点 除了上面的所有要求之外,如果我只想在需要时计算这个变量的值(因为计算它的计算成本很高),会发生什么呢。在这种情况下我该怎么办 不幸的是,您不能在任何给定时刻将变量设置为final。如果变量是final,则它可以(并且必须)在构造函数中初始化 您也可以这样做(以下代码

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


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

不幸的是,您不能在任何给定时刻将变量设置为final。如果变量是
final
,则它可以(并且必须)在构造函数中初始化

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


您可以从以下位置尝试memoize supplier:

Supplier something=Suppliers.memoize(新供应商(){
//繁重的计算
返回结果。
});
某事。get();
某事。get();//第二次调用将返回已记忆的对象。

看起来您需要延迟初始化。当某个结果由于某种原因被认为是昂贵的时,使用它是一种性能优化。目标是 延迟一个昂贵的计算,直到它是必要的 存储昂贵计算的结果,以便计算不需要再次重复

以下是一个例子:

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;
        }
    }
}
正如您所看到的,
数据
仅在需要时初始化

如果您的代码在多线程环境中工作,请小心,否则会出现问题。这是因为多个线程可以同时调用该方法。为了防止这种情况,我们可以使用
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
关键字仅允许一个线程可以输入和初始化
数据

您始终可以编写一个方法来计算最终变量的值,并在构造函数中调用该方法以将返回值分配给最终变量。为什么不呢?对于第二个问题,将布尔值传递给对象的构造函数,
shouldInitializeFinalVariable
,并根据这一点调用昂贵的方法,否则默认为无参数Constructor,我想知道除了谷歌自己的开发者之外,还有多少开发者在日常开发中使用番石榴?@svasa如果你开发一天没有使用番石榴,那么你可能做错了什么。@shmosel我不同意。在没有番石榴的情况下,完全可以编写整洁、高效、可维护、高可用性的代码。另一方面,我知道Guava是一个很好的库。毫无疑问,所有组织都允许他们的开发人员使用它,并提供具有Guava依赖性的产品吗?最后一个示例不适用于多线程,除非数据变得易变。
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;
        }
    }
}
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;
        }
    }
}