为什么整数在Java中是不可变的?

我知道整数在Java中是不可变的。 但为什么这样设计呢?

在提出这个问题之前,我通过了其他答案:

整数是不可改变的

i ++仍在为Java中的不可变Integer工作?

为什么Java包装类是不可变的?

但我找不到强制使用Integer不变的用例。 是否存在类似String的技术原因?

  1. 字符串在网络连接,数据库URL等中用作参数。如果它是可变的,它很容易被破坏。
  2. 支持StringPool工具。
  3. 支持将字符串用作参数的类加载机制。 字符串是可变的导致加载错误的类。

我知道像AtomicInteger这样的包装器是可变的。

更新:

从谈话中,没有普遍的理由可以强制整数是不可变的。 然而,通过做不可变,它提供了答案中提到的一些奖励。

比如安德烈的这句话

缓存的可能性。

其他人正在减少全球状态

更容易multithreading

您将找不到java.lang包装器必须是不可变的强制性原因。 仅仅因为这是一个设计决定 。 他们本来可以另有决定。 语言设计者必须在可变不可变之间做出选择。 他们选择了不变的 。 而已。

尽管有一些令人信服的 (IMO)原因使它们变得不可变

它与String一致。 您为String提供的不可变的相同推理也适用于Integer等(例如,考虑属性映射中的端口号)。 这通常适用于任何可变类型

不可变类型排除了过多的难以发现的错误,可以通过修改通过getter获得的值来非自愿地改变对象成员值。 当类型不可变时,它可以节省大量的防御性复制 。 最臭名昭着的例子是java.util.Date ,这通常很难使用,因为它是可变的 (除了API问题)。

同样不可变的类型允许使用共享实例,例如Integer对常用值的使用(参见Integer.valueOf(int) )。

价值1的身份能否改变? 可以变成2吗? 不。这就是为什么Integer和其他数字类型是不可变的。 他们的目的是模仿这种身份。

为了使对象引用封装一个受持有它的东西控制的值,必须应用以下三个条件之一:

  1. 对象的类必须是不可变的。

  2. 引用必须标识一个永远不会暴露于任何可能使其变异的实例。

  3. 绝不能与任何不受其持有者控制的对象共享引用,无论这样的东西是否会改变它。

保存Integer类型引用的代码通常是为了封装整数值。 使Integer不可变使得类可以自由地共享用于封装值的引用。 虽然有时候MutableInteger类本身有用[这样的东西可能比单元素int[]更清晰一点且比AtomicInteger更有效],但是不会将MutableInteger类传递给方法传递数字的方法; 为了给该方法一个存储数字的位置,我们会改为传递它。

整数文字(2,3)也是不可变的,例如int var=3; 它是可变的int变量(左边的var有侧)。 Integer的意图是“对象作为值”(右侧)而不是“对象作为变量”(左侧)。 由于Java使用引用,因此可变性可以在引用中或在对象内容中。 对象引用( Integer r=2;变量r Integer r=2; )可以是变量部分。 结果,通过变量引用提供可变性,而不是使用常量引用(常量r )和引用对象的可变内容。 他们可以使用类名Integer作为变量,但是对于不可变(右侧值)则需要另一个类名。 所以MutableIntegerImmutableInteger都在某些点的程序中使用。 然而,人们碰巧经常使用后者。 因此,早期Java开发人员决定使用较短的名称Integer作为后者( ImmutableInteger )。 有很多原因导致后者certificate更有用,这在本文的其他答案中有所解释。 两者都是可能的,它们都存在,只是对后者有更多的需求。