Java 不可变是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/279507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is meant by immutable?
提问by ashokgelal
This could be the dumbest question ever asked but I think it is quite confusing for a Java newbie.
这可能是有史以来最愚蠢的问题,但我认为对于 Java 新手来说,这很令人困惑。
- Can somebody clarify what is meant by immutable?
- Why is a
String
immutable? - What are the advantages/disadvantages of the immutable objects?
- Why should a mutable object such as
StringBuilder
be preferred over String and vice-verse?
- 有人可以澄清immutable是什么意思吗?
- 为什么是
String
不可变的? - 不可变对象的优点/缺点是什么?
- 为什么像这样的可变对象
StringBuilder
应该优先于 String ,反之亦然?
A nice example (in Java) will be really appreciated.
一个很好的例子(在 Java 中)将非常感激。
采纳答案by Douglas Leeder
Immutable means that once the constructor for an object has completed execution that instance can't be altered.
不可变意味着一旦对象的构造函数完成执行,该实例就无法更改。
This is useful as it means you can pass references to the object around, without worrying that someone else is going to change its contents. Especially when dealing with concurrency, there are no locking issues with objects that never change
这很有用,因为这意味着您可以传递对对象的引用,而不必担心其他人会更改其内容。特别是在处理并发时,永远不会改变的对象不存在锁定问题
e.g.
例如
class Foo
{
private final String myvar;
public Foo(final String initialValue)
{
this.myvar = initialValue;
}
public String getValue()
{
return this.myvar;
}
}
Foo
doesn't have to worry that the caller to getValue()
might change the text in the string.
Foo
不必担心调用者getValue()
可能会更改字符串中的文本。
If you imagine a similar class to Foo
, but with a StringBuilder
rather than a String
as a member, you can see that a caller to getValue()
would be able to alter the StringBuilder
attribute of a Foo
instance.
如果您想象一个与 类似的类Foo
,但使用 aStringBuilder
而不是 aString
作为成员,您可以看到调用者getValue()
将能够更改实例的StringBuilder
属性Foo
。
Also beware of the different kinds of immutability you might find: Eric Lippert wrote a blog articleabout this. Basically you can have objects whose interface is immutable but behind the scenes actual mutables private state (and therefore can't be shared safely between threads).
还要注意您可能会发现的不同类型的不变性:Eric Lippert 写了一篇关于此的博客文章。基本上你可以拥有接口不可变但在幕后实际可变私有状态的对象(因此不能在线程之间安全地共享)。
回答by stjohnroe
Once instanciated, cannot be altered. Consider a class that an instance of might be used as the key for a hashtable or similar. Check out Java best practices.
一经实例化,不可更改。考虑一个类,它的实例可能用作哈希表或类似的键。查看 Java 最佳实践。
回答by eishay
Immutable means that once the object is created, non of its members will change. String
is immutable since you can not change its content.
For example:
不可变意味着一旦对象被创建,它的成员都不会改变。String
是不可变的,因为您无法更改其内容。例如:
String s1 = " abc ";
String s2 = s1.trim();
In the code above, the string s1 did not change, another object (s2
) was created using s1
.
在上面的代码中,字符串 s1 没有改变,s2
使用s1
.
回答by Georgy Bolyuba
"immutable" means you cannot change value. If you have an instance of String class, any method you call which seems to modify the value, will actually create another String.
“不可变”意味着你不能改变价值。如果您有一个 String 类的实例,那么您调用的任何似乎修改该值的方法实际上都会创建另一个 String。
String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"
To preserve changes you should do something like this foo = foo.sustring(3);
要保留更改,您应该执行以下操作 foo = foo.sustring(3);
Immutable vs mutable can be funny when you work with collections. Think about what will happen if you use mutable object as a key for map and then change the value (tip: think about equals
and hashCode
).
当您使用集合时,不可变与可变可能会很有趣。想想如果您使用可变对象作为 map 的键然后更改值会发生什么(提示:考虑equals
和hashCode
)。
回答by Charles Bretana
One meaning has to do with how the value is stored in the computer, For a .Net string for example, it means that the string in memory cannot be changed, When you think you're changing it, you are in fact creating a new string in memory and pointing the existing variable (which is just a pointer to the actual collection of characters somewhere else) to the new string.
一种含义与值如何存储在计算机中有关,例如对于 .Net 字符串,这意味着内存中的字符串无法更改,当您认为您正在更改它时,实际上您正在创建一个新的内存中的字符串并将现有变量(它只是指向其他地方的实际字符集合的指针)指向新字符串。
回答by Jason Coco
Immutable objects are objects that can't be changed programmatically. They're especially good for multi-threaded environments or other environments where more than one process is able to alter (mutate) the values in an object.
不可变对象是不能以编程方式更改的对象。它们特别适用于多线程环境或其他多个进程能够更改(变异)对象中的值的环境。
Just to clarify, however, StringBuilder is actually a mutable object, not an immutable one. A regular java String is immutable (meaning that once it's been created you cannot change the underlying string without changing the object).
然而,澄清一下,StringBuilder 实际上是一个可变对象,而不是不可变对象。一个普通的java String 是不可变的(意味着一旦它被创建,你就不能在不改变对象的情况下改变底层的字符串)。
For example, let's say that I have a class called ColoredString that has a String value and a String color:
例如,假设我有一个名为 ColoredString 的类,它有一个字符串值和一个字符串颜色:
public class ColoredString {
private String color;
private String string;
public ColoredString(String color, String string) {
this.color = color;
this.string = string;
}
public String getColor() { return this.color; }
public String getString() { return this.string; }
public void setColor(String newColor) {
this.color = newColor;
}
}
In this example, the ColoredString is said to be mutable because you can change (mutate) one of its key properties without creating a new ColoredString class. The reason why this may be bad is, for example, let's say you have a GUI application which has multiple threads and you are using ColoredStrings to print data to the window. If you have an instance of ColoredString which was created as
在此示例中,ColoredString 被称为可变的,因为您可以更改(变异)其关键属性之一,而无需创建新的 ColoredString 类。这可能不好的原因是,例如,假设您有一个具有多个线程的 GUI 应用程序,并且您正在使用 ColoredStrings 将数据打印到窗口。如果你有一个 ColoredString 的实例,它被创建为
new ColoredString("Blue", "This is a blue string!");
Then you would expect the string to always be "Blue". If another thread, however, got ahold of this instance and called
那么你会期望字符串总是“蓝色”。但是,如果另一个线程获得此实例并调用
blueString.setColor("Red");
You would suddenly, and probably unexpectedly, now have a "Red" string when you wanted a "Blue" one. Because of this, immutable objects are almost always preferred when passing instances of objects around. When you have a case where mutable objects are really necessary, then you would typically guard the objet by only passing copies out from your specific field of control.
当您想要一个“蓝色”字符串时,您会突然地,并且可能出乎意料地现在拥有一个“红色”字符串。因此,在传递对象实例时,几乎总是首选不可变对象。当您遇到确实需要可变对象的情况时,您通常会通过仅从您的特定控制领域传递副本来保护对象。
To recap, in Java, java.lang.String is an immutable object (it cannotbe changed once it's created) and java.lang.StringBuilder is a mutable object because it can be changed without creating a new instance.
回顾一下,在 Java 中, java.lang.String 是一个不可变对象(一旦创建就无法更改),而 java.lang.StringBuilder 是一个可变对象,因为它可以在不创建新实例的情况下进行更改。
回答by wen
I really like the explaination from SCJP Sun Certified Programmer for Java 5 Study Guide.
我真的很喜欢SCJP Sun Certified Programmer for Java 5 Study Guide 的解释。
To make Java more memory efficient, the JVM sets aside a special area of memory called the "String constant pool." When the compiler encounters a String literal, it checks the pool to see if an identical String already exists. If a match is found, the reference to the new literal is directed to the existing String, and no new String literal object is created.
为了提高 Java 的内存效率,JVM 留出了一个特殊的内存区域,称为“字符串常量池”。当编译器遇到字符串文字时,它会检查池以查看是否已存在相同的字符串。如果找到匹配项,则对新文字的引用将定向到现有字符串,并且不会创建新的字符串文字对象。
回答by user36393
An immutable object is the one you cannot modify after you create it. A typical example are string literals.
不可变对象是创建后无法修改的对象。一个典型的例子是字符串文字。
A D programming language, which becomes increasingly popular, has a notion of "immutability" through "invariant" keyword. Check this Dr.Dobb's article about it - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29. It explains the problem perfectly.
越来越流行的 AD 编程语言通过“不变”关键字具有“不变性”的概念。检查这篇 Dr.Dobb 关于它的文章 - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29。它完美地解释了这个问题。
回答by Bill Michell
Objects which are immutable can not have their state changed after they have been created.
不可变对象在创建后不能更改其状态。
There are three main reasons to use immutable objects whenever you can, all of which will help to reduce the number of bugs you introduce in your code:
尽可能使用不可变对象有三个主要原因,所有这些都将有助于减少您在代码中引入的错误数量:
- It is much easier to reason about how your program works when you know that an object's state cannot be changed by another method
- Immutable objects are automatically thread safe (assuming they are published safely) so will never be the cause of those hard-to-pin-down multithreading bugs
- Immutable objects will always have the same Hash code, so they can be used as the keys in a HashMap (or similar). If the hash code of an element in a hash table was to change, the table entry would then effectively be lost, since attempts to find it in the table would end up looking in the wrong place. This is the main reason that String objects are immutable - they are frequently used as HashMap keys.
- 当你知道一个对象的状态不能被另一种方法改变时,就更容易推理你的程序是如何工作的
- 不可变对象自动是线程安全的(假设它们是安全发布的),因此永远不会成为那些难以确定的多线程错误的原因
- 不可变对象将始终具有相同的哈希码,因此它们可以用作 HashMap(或类似的)中的键。如果哈希表中某个元素的哈希码要更改,则表条目实际上将丢失,因为尝试在表中查找它最终会在错误的位置查找。这是 String 对象不可变的主要原因 - 它们经常用作 HashMap 键。
There are also some other optimisations you might be able to make in code when you know that the state of an object is immutable - caching the calculated hash, for example - but these are optimisations and therefore not nearly so interesting.
当您知道对象的状态是不可变的时,您可能还可以在代码中进行一些其他优化 - 例如缓存计算出的哈希 - 但这些都是优化,因此并不是那么有趣。
回答by Bill Michell
Actually String is not immutable if you use the wikipedia definition suggested above.
如果您使用上面建议的维基百科定义,实际上 String 不是一成不变的。
String's state does change post construction. Take a look at the hashcode() method. String caches the hashcode value in a local field but does not calculate it until the first call of hashcode(). This lazy evaluation of hashcode places String in an interesting position as an immutable object whose state changes, but it cannot be observed to have changed without using reflection.
字符串的状态确实会在构建后发生变化。看看 hashcode() 方法。String 将 hashcode 值缓存在本地字段中,但直到第一次调用 hashcode() 时才会计算它。哈希码的这种懒惰评估将 String 作为一个不可变对象,其状态发生了变化,但如果不使用反射,则无法观察到它发生了变化。
So maybe the definition of immutable should be an object that cannot be observed to have changed.
所以也许 immutable 的定义应该是一个无法观察到改变的对象。
If the state changes in an immutable object after it has been created but no-one can see it (without reflection) is the object still immutable?
如果不可变对象在创建后状态发生变化但没有人可以看到它(没有反射),该对象是否仍然不可变?