如何初始化需要复杂计算的最终变量?
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
。
我是 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
。