Java不可变对象 [英] Java Immutable Objects

查看:186
本文介绍了Java不可变对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习不变性的概念.

I am learning the concept of immutability.

我了解,一旦创建了不可变的对象,它们就无法更改其值.

I understand that immutable objects cannot change their values once the object is created.

但是我不理解不可变对象的以下用法.

他们是

  • 是自动线程安全的,没有同步问题. How ? Proof ?
  • 不需要复制构造函数. How ? Any example ?
  • 不需要克隆How ? Any example ?
  • 的实现
  • 用作字段How ? Any example ?
  • 时不需要防御性地复制
  • 始终具有"failure atomicity" (a term used by Joshua Bloch):如果不可变对象引发异常,则永远不会将其置于不希望的状态或不确定的状态. How ? Any example ?
  • are automatically thread-safe and have no synchronization issues. How ? Proof ?
  • do not need a copy constructor. How ? Any example ?
  • do not need an implementation of clone How ? Any example ?
  • do not need to be copied defensively when used as a field How ? Any example ?
  • always have "failure atomicity" (a term used by Joshua Bloch) : if an immutable object throws an exception, it's never left in an undesirable or indeterminate state. How ? Any example ?

有人可以 详细 详细说明其中的每个要点吗?

Could someone please explain each of these points in detail with examples supporting it ?

谢谢.

推荐答案

..是自动线程安全的,并且没有同步问题

当两个不同的线程修改同一对象的状态时,会发生并发问题.不变的对象不能被修改,所以没有问题.

Concurrency problems happen when two different threads modify the state of the same object. Immutable objects can't be modified, so no problems.

示例:A String.可以毫无顾虑地将两个线程传递给同一个String,因为这两个线程都无法以任何方式对其进行修改.

Example: A String. Two threads can be passed the same String without worry since neither can mutate it in any way.

不需要复制构造函数

...,因为复制是对其进行突变的唯一方法.一种不变的对象的通用设计模式是,对每个修改"操作进行复制,然后对新对象执行该操作.

... because copy is the only way to mutate it. One common design pattern for immutable objects for every "modification" operation to make a copy and then perform the operation on the new object.

复制构造函数通常用于要更改而又不影响原始对象的对象.不可变对象总是(根据定义).

Copy constructors are usually used on objects that you want to change without affecting the original. This is always the case (by definition) with immutable objects.

对于String,所有方法和+运算符均返回新的String.

In the case of String, all the methods and the + operator return new Strings.

不需要克隆的实现

见上文.

用作字段时无需防御性复制

从前,我做了一些愚蠢的事情.我在列表中有一组枚举:

Once upon a time I did something silly. I had a set of enums in a List:

private static final List<Status> validStatuses;

static {
  validStatuses = new ArrayList<Status>();
  validStates.add(Status.OPEN);
  validStates.add(Status.REOPENED);
  validStates.add(Status.CLOSED);
}

此列表是从方法返回的:

This list was returned from a method:

public static List<Status> getAllStatuses() {
  return validStates;
}

我检索了该列表,但只想在界面中显示打开状态:

I retrieved that list but only wanted to show the open states in the interface:

List<Status> statuses = Status.getAllStatuses();
statuses.remove(Status.CLOSED);

太好了,它有效了!等等,现在所有状态列表仅显示这两个状态-即使在刷新页面后!发生了什么?我修改了一个静态对象.糟糕!

Great, it worked! Wait, now all status lists are showing only those two -- even after page refresh! What happened? I modified a static object. Oops.

我本可以在getAllStatuses的返回对象上使用防御性复制.或者,我可以在其中使用 Guava的ImmutableList 之类的东西第一名:

I could have used defensive copying on the return object of getAllStatuses. Or, I could use something like Guava's ImmutableList in the first place:

private static final List<Status> validStatuses =
    ImmutableList.of(Status.OPEN, Status.REOPENED, Status.CLOSED);

然后当我做一些愚蠢的事情时:

Then when I did something dumb:

List<Status> statuses = Status.getAllStatuses();
statuses.remove(Status.CLOSED);  // Exception!

始终具有失败原子性"(约书亚·布洛赫(Joshua Bloch)使用的术语):如果不可变对象抛出异常,则永远不会处于不希望或不确定的状态.

因为该类永远无法修改,所以修改所发出的所有状态都是完整的合格对象(因为它们无法更改,因此必须始终处于合格状态才有用).异常不会发出新对象,因此您永远不会有不希望的或不确定的状态.

Because the class can never be modified, all states emitted by modification are whole, qualified objects (because they cannot change, they must always be in a qualified state to be useful). An exception would not emit a new object and therefore you can never have an undesirable or indeterminate state.

这篇关于Java不可变对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆