java:示例中不可变对象的优点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5652652/
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
java: advantages of immutable objects in examples
提问by Nazerke
give me please examples where I could see advantages of immutable objects. Info I found in internet are concentrated in threads. I don't know about threads yet. would be great if the examples would use simple principles
请给我一些例子,让我可以看到不可变对象的优点。我在互联网上找到的信息集中在线程中。我还不知道线程。如果示例使用简单的原则,那就太好了
回答by Jay
Immutability is important in multi-threaded programs, because then you know that one thread won't corrupt a value used in another thread. But it's also useful in a single-threaded program.
不变性在多线程程序中很重要,因为这样您就知道一个线程不会破坏另一个线程中使用的值。但它在单线程程序中也很有用。
Here's a simple example:
这是一个简单的例子:
Integer i=Integer.valueOf(17);
foo(i);
bar(i);
You might well want to know, What value is passed to bar()?
您可能很想知道,传递给 bar() 的值是什么?
Suppose that foo() is a big, complex function. In this example, I know for an absolute fact that when foo completes, i is still equal to 17, because an Integer is immutable. Were that not true, I would have to study foo to tell if it might be changed or not.
假设 foo() 是一个大而复杂的函数。在这个例子中,我知道一个绝对的事实,当 foo 完成时,i 仍然等于 17,因为 Integer 是不可变的。如果那不是真的,我将不得不研究 foo 以判断它是否可能会改变。
Here's a slightly more complex example. Suppose I have some object that resembles an Integer, but is mutable. Let's call it MutableInteger. Then say I write this:
这是一个稍微复杂的例子。假设我有一些类似于 Integer 的对象,但它是可变的。我们称之为 MutableInteger。然后说我写这个:
MutableInteger currentInventory=findQtyInInventory();
MutableInteger neededInventory=currentInventory; // copy current for starters
... bunch of other code ...
neededInventory.subtract(allocatedToSales);
currentInventory.add(arriving);
... bunch of more code ...
if (neededInvenory.compareTo(currentInventory)>0)
display("Shortage!");
Do you see the problem with the above? neededInventory and currentInventory point to the same object. All the adds and subtracts are really acting on the same value, not two different values, so when we get to the test, it will always be equal. The above code would never work if the objects are mutable. If they are immutable, the adds and subtracts would have to return a result object rather than updating in place, and that would work.
你看到上面的问题了吗?requiredInventory 和 currentInventory 指向同一个对象。所有的加法和减法实际上都作用于同一个值,而不是两个不同的值,所以当我们进行测试时,它总是相等的。如果对象是可变的,上面的代码将永远不会工作。如果它们是不可变的,那么加法和减法就必须返回一个结果对象,而不是就地更新,这会起作用。
Years ago I used a Fortran compiler where integers WERE mutable. We had a function that accepted several parameters, one of them an integer. In some rare cases, the function updated the integer. Then one day someone wrote a call to this function passing the constant "2" as the integer. The function decided to update the parameter, thus changing the "constant" 2 to 1! Every other place in the program that used a constant 2 now mysteriously got the value 1 instead. This took a long time to debug.
几年前,我使用了 Fortran 编译器,其中整数是可变的。我们有一个接受多个参数的函数,其中一个是整数。在极少数情况下,函数更新了整数。然后有一天有人写了一个对这个函数的调用,将常量“2”作为整数传递。该函数决定更新参数,从而将“常量”2 更改为 1!程序中使用常量 2 的所有其他地方现在都神秘地得到了值 1。这花了很长时间来调试。
回答by Michael Borgwardt
It's not a concept that can be usefully explained with examples. The advantage of immutable objects is that you know their data cannot change, so you don't have to worry about that. You can pass them around freely without having to remember whether a method you pass them to could change them in a way your code is not prepared to handle. That makes working with immutable data easier.
这不是一个可以用例子有用地解释的概念。不可变对象的优点是你知道它们的数据不会改变,所以你不必担心。您可以自由地传递它们,而不必记住传递给它们的方法是否会以您的代码不准备处理的方式更改它们。这使得处理不可变数据变得更加容易。
With multiple threads, this advantage is just more important because bugs based on multiple threads changing data in ways it's not supposed to be changed are usually not reproducible - they depend on timing and thus sometimes happen and sometimes not, which makes them very hard to analyze and fix.
对于多线程,这种优势更为重要,因为基于多线程以不应该更改的方式更改数据的错误通常是不可重现的 - 它们取决于时间,因此有时会发生有时不会发生,这使得它们很难分析并修复。
回答by mdma
Immutable objects are useful when objects are generally shared - not just with threading, but in single-threaded programs also where an object has many clients.
当对象通常被共享时,不可变对象很有用 - 不仅在线程中,而且在单线程程序中,对象有许多客户端时也是如此。
For example, String
is probably the most used immutable object in Java. It's immutable to stop users of that string from changing it's contents. If String
was mutable, it would mean each user would have to create a unique copy of that string to ensure no-one else was changing it.
例如,String
可能是 Java 中最常用的不可变对象。阻止该字符串的用户更改其内容是不可变的。如果String
是可变的,则意味着每个用户都必须创建该字符串的唯一副本,以确保没有其他人更改它。
Immutable data also has security implications. For example, a security token associated with a user should be immutable, otherwise a rogue program could easily change the user associated with that token.
不可变数据也有安全隐患。例如,与用户关联的安全令牌应该是不可变的,否则流氓程序可以轻松更改与该令牌关联的用户。
回答by Konrad Garus
As you already know, it's a great pattern for multithreading.
正如您已经知道的那样,这是一个很好的多线程模式。
It also means much better encapsulation. You can pass those objects around and share them and you never, ever have to worry that someone changes your object's state.
这也意味着更好的封装。您可以传递这些对象并共享它们,而且您永远不必担心有人会更改您对象的状态。
There are some great examples in Java core library. Number subclasses are one, but I think the best example is String
. You pass them around, concatenate, get substrings etc. and never need to think about other places. If it was mutable like C/C++ char[]
, you would always need to keep that in mind.
Java 核心库中有一些很好的例子。Number 子类是一个,但我认为最好的例子是String
. 您可以传递它们、连接、获取子字符串等,而无需考虑其他地方。如果它像 C/C++ 一样是可变的char[]
,那么您将始终需要牢记这一点。
For the same reason it also leads to more readable and maintainable code. No need to care about other users of the object.
出于同样的原因,它还导致代码更具可读性和可维护性。无需关心对象的其他用户。
Both these reasons lead us to another important pattern called Value Object. In brief, it makes sense when you care about some particular value(a date, a number, a string, an interval, money, or some slightly more complex objects if you need), but the value itself has no identity, i.e. it has exactly the same meaning regardless of context.
这两个原因将我们引向另一个重要的模式,称为Value Object。简而言之,当您关心某个特定值(日期、数字、字符串、间隔、金钱或一些稍微复杂的对象,如果您需要)时,这是有意义的,但值本身没有 identity,即它具有无论上下文如何,完全相同的含义。
回答by Dunnie
As Java returns by value (i.e. object references are returned from methods), if for example I return a String like so:
由于 Java 按值返回(即对象引用从方法返回),例如,如果我返回这样的字符串:
private String myString = "foo";
public String getString() {
return this.myString;
}
and the String class wasn't immutable, then the caller of getString()
could modify myString
, which may not be the desired behaviour; other parts of the system might not want or expect myString
to change. So the caller can only change the object which myString
points to, not myString
itself.
并且 String 类不是不可变的,那么调用者getString()
可以修改myString
,这可能不是所需的行为;系统的其他部分可能不想或不希望myString
改变。所以调用者只能改变myString
指向的对象,不能改变它myString
本身。
回答by ColinD
It's kind of tautological, but the main advantage of immutable objects is that they can't change. When objects can change, you have to think about what might happen with them. You have to think about how, when and why you want to change them. You have to think about what other code in your application might have access to the same object, and what it might change without you knowing. Immutable objects effectively reduce the number (and granularity) of "moving parts" you have to juggle in your system and make your life easier.
这有点重言式,但不可变对象的主要优点是它们不能改变。当对象可以更改时,您必须考虑它们可能会发生什么。您必须考虑如何、何时以及为什么要更改它们。您必须考虑应用程序中的哪些其他代码可以访问同一个对象,以及在您不知道的情况下它可能会更改哪些内容。不可变对象有效地减少了您必须在系统中处理的“移动部件”的数量(和粒度),并使您的生活更轻松。