在Java中,我们使用final带变量的关键字来指定其值不被更改.但我发现你可以改变类的构造函数/方法中的值.同样,如果变量是,static那么它是编译错误.
这是代码:
import java.util.ArrayList;
import java.util.List;
class Test {
private final List foo;
public Test()
{
foo = new ArrayList();
foo.add("foo"); // Modification-1
}
public static void main(String[] args)
{
Test t = new Test();
t.foo.add("bar"); // Modification-2
System.out.println("print - " + t.foo);
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码工作正常,没有错误.
现在将变量更改为static:
private static final List foo;
Run Code Online (Sandbox Code Playgroud)
现在是编译错误.这final真的有用吗?
如何将ConcurrentHashMap的性能与HashMap进行比较,特别是.get()操作(我特别感兴趣的是只有少数几个项目的情况,范围可能在0-5000之间)?
有没有理由不使用ConcurrentHashMap而不是HashMap?
(我知道不允许使用空值)
更新
只是为了澄清,显然在实际并发访问的情况下性能会受到影响,但是如何在没有并发访问的情况下比较性能呢?
这是来自JCiP的示例。
public class Unsafe {
// Unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
}
public class Holder {
private int n;
public Holder(int n) {
this.n = n;
}
public void assertSanity() {
if (n != n) {
throw new AssertionError("This statement is false.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
在第34页上:
[15]这里的问题不是Holder类本身,而是Holder没有正确发布。但是,可以通过将n字段声明为final来使Holder免受不适当发布的影响,这将使Holder不变。
从这个答案:
final的规范(请参阅@andersoj的答案)保证当构造函数返回时,将对final字段进行适当的初始化(从所有线程可见)。
从维基:
例如,在Java中,如果已经内联了对构造函数的调用,则一旦分配了存储空间,但是在内联的构造函数初始化对象之前,可以立即更新共享变量。
我的问题是:
因为:(可能不正确,我不知道。)
a)可以在内联构造函数初始化对象之前立即更新共享变量。
b)只有在构造函数返回时,才能保证对final字段进行正确的初始化(从所有线程可见)。
另一个线程是否可能看到默认值holder.n?(即,另一个线程holder在holder构造函数返回之前获得对它的引用。)
如果是这样,那么您如何解释以下声明?
通过将n字段声明为final,可以使Holder免受不适当发布的影响,这将使Holder不可变
编辑: …