所有原始包装类都是不可变对象吗?

Posted

技术标签:

【中文标题】所有原始包装类都是不可变对象吗?【英文标题】:Are all primitive wrapper classes immutable objects? 【发布时间】:2011-09-04 05:06:23 【问题描述】:

Java 中的字符串是不可变的。其他不可变对象是什么?

【问题讨论】:

Immutable Classes 的可能重复项 【参考方案1】:

是的,当然。包装类是不可变的。

您可以阅读Why wrapper classes are immutable in java? 以了解包装类的不变性。

【讨论】:

【参考方案2】:

一个奇怪的“包装”类是Void,它没有任何有效的对象,不可变的或其他的。只能设置为null。

Void 的一个用途是标记没有值的通用返回类型。 (不能使用原始类型或void

例如

Callable<Void> callable = new Callable<Void>() 
    public Void call() 
         // do something
        return null;
    
;

尽管Date 在技术上是可变的,但我仍将其描述为“通过约定不可变”。通常理解或假设您不会更改 Date 对象,而是会像任何其他不可变对象一样替换它以更改它。

【讨论】:

【参考方案3】:

任何不给你任何方法来改变其中数据的类型都是不可变的——就这么简单。是的,所有原始包装器类型都是不可变的1String 也是如此。 UUID、URL 和 URI 是其他示例。

虽然内置 Java API 中的 CalendarDate 是可变的,但 Joda Time 中的许多类型是不可变的 - 在我看来,这就是 Joda 的一个原因时间更容易处理。如果一个对象是不可变的,您可以在代码中的其他地方保留对它的引用,而不必担心其他代码是否会进行更改 - reason 更容易你的代码。


1 我的意思是 java.lang.Integer 等。正如其他地方所指出的那样,Atomic* 类是可变的,并且确实必须为了服务于它们的目的.在我看来,“标准的原始包装类集”和“包装原始值的类集”是有区别的。

您可以非常轻松地编写自己的可变包装类:

public class MutableInteger

    private int value;

    public MutableInteger(int value) 
    
         this.value = value;
    

    public int getValue()
    
        return value;
    

    public void setValue(int value)
    
        this.value = value;
    

如您所见,包装类本质上没有什么是不可变的——只是标准的设计是不可变的,因为它没有提供任何方法更改包装的值。

请注意,这允许在装箱时重复使用相同的对象,以获得通用值:

Integer x = 100;
Integer y = 100;
// x and y are actually guaranteed to refer to the same object

Integer a = 1000;
Integer b = 1000;
// a and b *could* refer to the same object, but probably won't

【讨论】:

对乔达时间的看法。这也是它被认为是 JDK 中新时代 API 的基础的原因之一。 我知道这个帖子已经在 2 年前得到回答,但为了我的困惑,我需要知道。 @JonSkeet 你为什么说 Integer a = 1000Integer b = 1000 a 和 b 可以指同一个对象,但可能不是?而在Integer x = 100Integer y = 100 x 和 y 保证引用同一个对象? @GrahamGriffiths:价值观确实如此。见docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7的最后几段 @gkns: 不是 some JVM...all 遵循语言规范的 JVM,值在 -128 到 +127(不是另一边)。但是,某些 JVM 可能会缓存 更多 个值。 Java 语言规范确实要求表示 -128 和 127 之间的整数值的 Integer 实例如果表示相同的整数值,则保证它们是相同的。见JLS § 5.1.7。【参考方案4】:

在 Java 5 之前,所有 primitive wrapper classes 都是不可变的。

但是,Java 5 中引入的 atomic wrapper classes(AtomicIntegerAtomicLongAtomicBooleanAtomicReference&lt;V&gt;)是可变的。

【讨论】:

虽然我当然同意 AtomicInteger 等是可变的,但我不认为它们通常被称为“原始包装类”,因为它们与原始类型的关联并不那么紧密作为整数等......例如,他们不参与拳击。不过,提出它们很有用。 @Jon,说得好。我想它们有时被认为是原始包装器,因为 AtomicIntegerAtomicLong 派生自 Number,例如 IntegerLong 是的。我在回答中对此进行了更多讨论-希望您不介意我从您的回答中汲取灵感:) @Jon,你的意思是,与我从你那里获得灵感的所有时间相反?请帮助自己:)

以上是关于所有原始包装类都是不可变对象吗?的主要内容,如果未能解决你的问题,请参考以下文章

java中是啥是不可变对象和可变对象

可变对象与不可变对象

js数据类型

什么是不可变对象,它对写并发应用有什么帮助?

不可变类

不可变类