不可变(immutable)字符串。Java 中的对象要么是可变的,要么是不可变的;这取决于对象如何被修改。

在本节中,我们将讨论 Java 中的可变对象和不可变对象。接下来,我们将看到它们之间的区别。

什么是可变对象

可变对象是初始化后其值可以被更改的对象。在对象创建后,我们可以更改对象的值,例如字段和状态。例如,Java.util.DateStringBuilderStringBuffer 等。

当我们更改现有可变对象时,不会创建新对象;而是会修改现有对象的值。这些对象类提供了更改自身的方法。

可变对象提供 Getter 和 Setter(get() 和 set() 方法)。可变对象可能线程安全,也可能不线程安全。

什么是不可变对象

不可变对象是初始化后其值无法被更改的对象。一旦对象创建,我们就无法更改任何内容。例如,原始类型对象intlongfloatdouble所有 旧类包装类String 类 等。

简而言之,不可变意味着未修改或不可更改。一旦创建了不可变对象,其对象值和状态就无法更改。

不可变对象仅提供 Getter(get() 方法),而不提供 Setter(set() 方法)。

让我们看看如何创建可变和不可变对象的类。

如何创建可变类

创建可变类需要以下两点:

  • 修改字段值的方法
  • 对象的 Getters 和 Setters

考虑下面可变类的示例

输出

JavaTpoint
Java Training

从上面的例子中,我们使用 setName 方法更改了 name 的值。

如何创建不可变类

创建不可变类需要以下几点:

  • Final 类,声明为 final,以便它不能被继承。
  • 所有字段都应该是 private,以阻止对字段的直接访问。
  • 没有 Setter
  • 所有可变字段都应该声明为 final,以便一旦初始化就不能再次迭代。

考虑下面的示例

输出

Core Java Training

因此,我们讨论了可变和不可变对象及类。接下来,让我们讨论它们之间的区别。

可变对象和不可变对象之间的区别

以下是 Java 中可变对象和不可变对象之间的一些关键区别:

  • 可变对象可以在不添加新对象的情况下更改为任何值或状态。而不可变对象一旦创建,就不能更改其值或状态。对于不可变对象,每当我们更改对象状态时,都会创建一个新对象。
  • 可变对象提供方法来更改对象的内容。相比之下,不可变对象不提供更改值的方法。
  • 可变对象同时支持 setter 和 getter。相比之下,不可变对象仅支持 getter,不支持 setter。
  • 可变对象可能线程安全,也可能不线程安全,但不可变对象默认是线程安全的。
  • 可变类的例子有 StringBuffer、Java.util.Date、StringBuilder 等。而不可变对象包括旧类、包装类、String 类等。

考虑下表

可变不可变
我们可以在初始化后更改可变对象的值。一旦初始化了不可变对象,我们就不能更改其值。
状态可以改变。状态不能改变。
在可变对象中,不会形成新对象。在不可变对象中,当对象的值被更改时,会形成一个新对象。
它提供了更改对象的方法。它不提供任何方法来更改对象的值。
它支持 get() 和 set() 方法来处理对象。它仅支持 get() 方法来传递对象的值。
可变类可能线程安全,也可能不线程安全。不可变类是线程安全的。
创建可变类的要素是修改字段的方法、getter 和 setter。创建不可变类的要素是 final 类、private 字段、final 可变对象。

为什么 Java 中的 String 是不可变的

Java 中的 String 是一个非常特殊的类,因为它几乎在所有 Java 程序中使用。因此,为了提高性能和安全性,它是不可变的。让我们详细了解一下。

在 Java 中,字符串使用字面量(literals)的概念。假设我们有一个对象,它有许多引用变量。在这种情况下,如果我们更改一个引用变量的值,它将影响整个对象及其所有值。

除了上述原因外,以下原因也使得 String 成为不可变的:

不可变对象非常简单,不需要同步,并且天生就是线程安全的。但是,不可变对象是构建其他对象的良好基础,因此我们需要特别小心地对待它们。

大多数开发人员会将 String 设为 final 对象,以便以后不能修改它。

结论

我们已经讨论了 Java 中的可变和不可变对象,现在我们对可变和不可变对象及类有了清晰的理解。此外,我们还看到了如何创建可变和不可变类。

需要注意的是,可变对象一旦初始化就可以更改其值和状态,并且可能线程安全,也可能不线程安全。相比之下,不可变对象不能更改其状态和值,并且默认是线程安全的。