java:示例中不可变对象的优点
请给我一些例子,让我可以看到不可变对象的优点。我在互联网上找到的信息都集中在线程中。我还不知道线程。如果示例能够使用简单的原理那就太好了
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
请给我一些例子,让我可以看到不可变对象的优点。我在互联网上找到的信息都集中在线程中。我还不知道线程。如果示例能够使用简单的原理那就太好了
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(8)
不变性在多线程程序中很重要,因为这样您就知道一个线程不会破坏另一个线程中使用的值。但它在单线程程序中也很有用。
这是一个简单的例子:
您可能很想知道,传递给 bar() 的值是什么?
假设 foo() 是一个大而复杂的函数。在这个例子中,我知道一个绝对的事实:当 foo 完成时,i 仍然等于 17,因为 Integer 是不可变的。如果不是这样,我将不得不研究 foo 来判断它是否可以改变。
这是一个稍微复杂的例子。假设我有一些类似于整数但可变的对象。我们称之为 MutableInteger。然后说我这样写:
你看到上面的问题了吗? needInventory 和 currentInventory 指向同一个对象。所有的加法和减法实际上都作用于相同的值,而不是两个不同的值,因此当我们进行测试时,它总是相等的。如果对象是可变的,上面的代码将永远不会工作。如果它们是不可变的,则加法和减法必须返回结果对象,而不是就地更新,这是可行的。
几年前,我使用了 Fortran 编译器,其中整数是可变的。我们有一个函数接受多个参数,其中之一是整数。在极少数情况下,该函数会更新整数。然后有一天,有人编写了对该函数的调用,传递常量“2”作为整数。该函数决定更新参数,从而将“常量”2更改为1!程序中所有其他使用常量 2 的地方现在都神秘地得到了值 1。这花了很长时间来调试。
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:
You might well want to know, What value is passed to 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.
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:
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.
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.
这不是一个可以通过示例进行有效解释的概念。不可变对象的优点是你知道它们的数据不能改变,所以你不必担心这一点。您可以自由地传递它们,而不必记住传递它们的方法是否会以您的代码不准备处理的方式更改它们。这使得处理不可变数据变得更加容易。
对于多线程,这种优势更加重要,因为基于多线程以不应该更改的方式更改数据的错误通常是不可重现的 - 它们取决于时间,因此有时会发生,有时不会,这使得它们很难分析并修复。
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.
正如您已经知道的,这是一个很好的多线程模式。
它还意味着更好的封装。您可以传递这些对象并共享它们,并且您永远不必担心有人更改您的对象的状态。
Java 核心库中有一些很棒的示例。数字子类是其中之一,但我认为最好的例子是
String
。您可以传递它们、连接、获取子字符串等,而无需考虑其他地方。如果它像 C/C++char[]
一样是可变的,那么您始终需要牢记这一点。出于同样的原因,它也会导致代码更具可读性和可维护性。无需关心该对象的其他用户。
这两个原因将我们引向另一个重要的模式,称为值对象。简而言之,当您关心某些特定值(日期、数字、字符串、间隔、金钱或一些稍微复杂的对象(如果需要)时,这是有意义的,但是该值本身没有身份,即无论上下文如何,它都具有完全相同的含义。
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.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.
由于 Java 按值返回(即从方法返回对象引用),如果我像这样返回一个 String:
并且 String 类不是不可变的,那么
getString()
的调用者可以修改myString
,这可能不是所需的行为;系统的其他部分可能不希望或期望myString
发生变化。因此调用者只能更改myString
指向的对象,而不能更改myString
本身。As Java returns by value (i.e. object references are returned from methods), if for example I return a String like so:
and the String class wasn't immutable, then the caller of
getString()
could modifymyString
, which may not be the desired behaviour; other parts of the system might not want or expectmyString
to change. So the caller can only change the object whichmyString
points to, notmyString
itself.这有点同义反复,但不可变对象的主要优点是它们无法更改。当对象可以改变时,你必须考虑它们可能会发生什么。你必须考虑如何、何时以及为何要改变它们。您必须考虑应用程序中的哪些其他代码可能可以访问同一对象,以及它可能会在您不知情的情况下更改哪些内容。不可变对象有效地减少了您必须在系统中处理的“移动部件”的数量(和粒度),让您的生活更轻松。
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.
当对象通常共享时,不可变对象非常有用 - 不仅在线程中,而且在对象有许多客户端的单线程程序中。
例如,
String
可能是 Java 中最常用的不可变对象。阻止该字符串的用户更改其内容是不可变的。如果String
是可变的,则意味着每个用户都必须创建该字符串的唯一副本,以确保没有其他人更改它。不可变数据也有安全隐患。例如,与用户关联的安全令牌应该是不可变的,否则流氓程序可以轻松更改与该令牌关联的用户。
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. IfString
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.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.
这里的主要思想是通过使用不可变对象使类线程安全。我认为这篇文章对此很值得一读。
希望这有帮助!
The main idea here is to make your classes thread safe by using immutable objects. I think this article is a good read on this.
Hope this helps!
一个很好的例子是
String
类:关于不可变对象的原因的一个很好的总结可以在 此处
A good example is the
String
class:A good summary of reasons for immutable objects can be found here