它应该是所有领域,包括超级领域,有目的不可变的java类'final'为了线程安全或足够没有修饰符方法吗?最终字段和线程安全
假设我有一个非final字段的POJO,其中所有字段都是一些不可变类的类型。这个POJO有getters-setters,并且有一个构造函数来设置一些初始值。如果我通过敲除修饰符方法来扩展此POJO,从而使其不可变,扩展类将是线程安全的吗?
它应该是所有领域,包括超级领域,有目的不可变的java类'final'为了线程安全或足够没有修饰符方法吗?最终字段和线程安全
假设我有一个非final字段的POJO,其中所有字段都是一些不可变类的类型。这个POJO有getters-setters,并且有一个构造函数来设置一些初始值。如果我通过敲除修饰符方法来扩展此POJO,从而使其不可变,扩展类将是线程安全的吗?
为了以线程安全的方式使用不带final
字段的有效不可变对象,需要在初始化后使对象对其他线程可用时使用安全发布习惯用法之一,否则这些线程可以看到部分初始化的对象状态(从Java Concurrency in Practice):
- 初始化从静态初始化的对象引用;
- 将引用存储到易失性字段或AtomicReference中;
- 将引用存储到正确构造的对象的最终字段中;或
- 将对其的引用存储到由锁正确保护的字段中。
声明你的不可变对象final
发布此限制的领域(即它保证,如果其他线程看到该对象的引用,他们也看到了完全初始化状态,其final
场)。但是,通常情况下,它并不能保证其他线程在发布时能够看到对象的引用,因此您可能仍然需要使用安全发布来确保它。
请注意,如果你的对象实现了接口,您可以使用Collections.unmodifiableList()
使用的方式,等:
class ImmutableFooWrapper implements IFoo {
private final IFoo delegate; // final provides safe publication automatically
public ImmutableFooWrapper(IFoo delegate) {
this.delegate = delegate;
}
...
}
public IFoo immutableFoo(IFoo foo) {
return new ImmutableFooWrapper(foo);
}
你是什么意思*敲出修饰符方法*修饰符方法?抛出所有setter的异常?这会违反[Liskov替代原则](http://en.wikipedia.org/wiki/Liskov_substitution_principle)。但是,是的,这个类会**是线程安全的。 –
是的,抛出一个运行时异常或用一个空的主体覆盖它们可能有一些日志记录。我知道这是违反LSP的。 – pcjuzer