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

108

请问有人能够用示例说明可变对象和不可变对象的区别吗?


4
String类是不可变对象的一个很好的例子。 - Qwerky
请参阅可变对象与不可变对象(非特定于Java)。 - Péter Török
顺便提一下,请查看com.jcabi.aspects.Immutable注释。 - yegor256
5个回答

133

可变对象具有可以更改的字段,不可变对象在创建后没有可以更改的字段。

非常简单的不可变对象是一个没有任何字段的对象。 (例如简单的比较器实现)。

class Mutable{
  private int value;

  public Mutable(int value) {
     this.value = value;
  }

  //getter and setter for value
}

class Immutable {
  private final int value;

  public Immutable(int value) {
     this.value = value;
  }

  //only getter
}

69

可变对象可以在构造后更改其字段。不可变对象则不能。

public class MutableClass {

 private int value;

 public MutableClass(int aValue) {
  value = aValue;
 }

 public void setValue(int aValue) {
  value = aValue;
 }

 public getValue() {
  return value;
 }

}

public class ImmutableClass {

 private final int value;
 // changed the constructor to say Immutable instead of mutable
 public ImmutableClass (final int aValue) {
  //The value is set. Now, and forever.
  value = aValue;
 }

 public final getValue() {
  return value;
 }

}

5
和你之前回答 Ralph 一样,我也给你点赞。不过我想更明确地表达一下。 - KNU

32

不可变对象就是指一旦构造完成,对象的状态(即对象的数据)就无法改变的对象。JDK 中的不可变对象包括 String 和 Integer。

例如:(Point 是可变的,而 String 是不可变的)

     Point myPoint = new Point( 0, 0 );
    System.out.println( myPoint );
    myPoint.setLocation( 1.0, 0.0 );
    System.out.println( myPoint );

    String myString = new String( "old String" );
    System.out.println( myString );
    myString.replaceAll( "old", "new" );
    System.out.println( myString );

输出结果为:

java.awt.Point[0.0, 0.0]
java.awt.Point[1.0, 0.0]
old String
old String

好的老式Effective Java。 - maffo
这就是我正在寻找的...谢谢。 - HybrisHelp
myString.replaceAll("old", "new"); 这段代码应该改为 myString=myString.replaceAll("old", "new"); 我认为你使用方法不正确。 - Tugrul
5
@TugrulAsik - 我的朋友用正确的方式使用了它。replace/replaceAll方法将返回值。如果您想将其存储到字符串中并使用它,可以将其存储到相同的字符串中或创建一个新的字符串对象并使用它。 - Arundev
当执行 myString.replaceAll("old", "new") 时,到底发生了什么?它是什么都没做还是创建了一个新的字符串值为 "new String",但由于我们没有存储它,所以它丢失了。具体发生了什么? - ARK

22

Immutable 对象的状态是不可更改的。

例如,String

String str= "abc";//a object of string is created
str  = str + "def";// a new object of string is created and assigned to str

15

从JVM的角度来看,它们并没有区别。不可变对象没有可以改变实例变量的方法,并且实例变量是私有的;因此,在创建之后您无法更改它。一个著名的例子是String。您没有像setString或setCharAt这样的方法。而且 s1 = s1 + "w" 将创建一个新字符串,原始字符串被放弃了。 那就是我的理解。


2
...而且所有实例变量都是私有的!(否则 -> 可变) - Andreas Dolk
1
@Andreas_D - 谢谢您的提醒。我想我把它当作理所当然了。 - LLS
1
点赞了“从JVM的角度来看,它们并没有区别”。 - khawarizmi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接