gpt4 book ai didi

java - 不可变对象(immutable对象)在 Java 中完全初始化后是否发布?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:39:25 24 4
gpt4 key购买 nike

我正在阅读 Fred Long 撰写的 Java 并发指南 中有关不可变对象(immutable对象)和线程安全的内容。

这是书中的一段代码。

// Immutable Helper
public final class Helper {
private final int n;

public Helper(int n) {
this.n = n;
}
// ...
}

// and a mutable Foo class:
final class Foo {
private Helper helper;

public Helper getHelper() {
return helper;
}

public void setHelper(int num) {
helper = new Helper(num);
}
}

代码片段后面是解释:

The getHelper() method publishes the mutable helper field. Because the Helper class is immutable, it cannot be changed after it is initialized. Furthermore, because Helper is immutable, it is always constructed properly before its reference is made visible in compliance with guideline “TSM03-J. Do not publish partially initialized objects” on page 162.

现在让我们打开他们提到的第 162 页。这是另一个代码片段。

class Foo {
private Helper helper;

public Helper getHelper() {
return helper;
}

public void initialize() {
helper = new Helper(42);
}
}

public class Helper {
private int n;

public Helper(int n) {
this.n = n;
}

}

后面是自己的解释:

If a thread accesses helper using the getHelper() method before the initialize() method has been called, the thread will observe an uninitialized helper field. Later, if one thread calls initialize() and another calls getHelper(), the second thread might observe one of the following:

  • the helper reference as NULL,
  • a fully initialized Helper object with the n field set to 42,
  • a partially initialized Helper object with an uninitialized n that contains the default value 0.

所以我加粗的两个陈述不是自相矛盾吗?


A写了一段代码来测试案例,跑了几次,一直没有得到0。只有null或者42。下面是我的代码:

package com.sample;

public class Main {

public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
Foo foo = new Foo();
Initer initer = new Initer(foo);
Getter getter = new Getter(foo);
initer.start();
getter.start();
}
}

static class Getter extends Thread {

private Foo foo;

Getter(Foo foo) {
this.foo = foo;
}

@Override
public void run() {
System.out.println(foo.getHelper());
}
}

static class Initer extends Thread {

private Foo foo;

Initer(Foo foo) {
this.foo = foo;
}

@Override
public void run() {
foo.initialize();
}
}

static class Foo {
private Helper helper;

public Helper getHelper() {
return helper;
}

public void initialize() {
helper = new Helper(42);
}
}

public static class Helper {
private int n;

public Helper(int n) {
this.n = n;
}

@Override
public String toString() {
return Integer.toString(n);
}
}

}

最佳答案

这两种说法并不矛盾。如果第一个示例字段 nfinal。这就是 Helper 类不可变的原因。在第二个示例中,n 不是最终的,Helper 不是不可变的,这意味着可以返回部分初始化的实例。

就用您的代码观察这一点而言,Peter 是对的,由于多种原因很难在实践中进行测试。

关于java - 不可变对象(immutable对象)在 Java 中完全初始化后是否发布?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35875055/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com