本文翻译自:What is meant by immutable?

This could be the dumbest question ever asked but I think it is quite confusing for a Java newbie. 这可能是有史以来最愚蠢的问题,但我认为Java新手很混乱。

  1. Can somebody clarify what is meant by immutable ? 有人可以澄清不可变的含义吗?
  2. Why is a String immutable? 为什么String不可变的?
  3. What are the advantages/disadvantages of the immutable objects? 不可变对象有哪些优点/缺点?
  4. Why should a mutable object such as StringBuilder be preferred over String and vice-verse? 为什么像StringBuilder这样的可变对象比String更受欢迎?

A nice example (in Java) will be really appreciated. 一个很好的例子(在Java中)将非常感激。


#1楼

参考:https://stackoom.com/question/1AiB/不可变的意思是什么


#2楼

An immutable object is an object where the internal fields (or at least, all the internal fields that affect its external behavior) cannot be changed. 不可变对象是一个对象,其中无法更改内部字段(或至少影响其外部行为的所有内部字段)。

There are a lot of advantages to immutable strings: 不可变字符串有很多优点:

Performance: Take the following operation: 表现:采取以下操作:

String substring = fullstring.substring(x,y);

The underlying C for the substring() method is probably something like this: substring()方法的底层C可能是这样的:

// Assume string is stored like this:
struct String { char* characters; unsigned int length; };// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{struct String* out = malloc(sizeof(struct String));out->characters = in->characters + begin;out->length = end - begin;return out;
}

Note that none of the characters have to be copied! 请注意, 不得复制任何字符! If the String object were mutable (the characters could change later) then you would have to copy all the characters, otherwise changes to characters in the substring would be reflected in the other string later. 如果String对象是可变的(字符可能会在以后更改),那么您必须复制所有字符,否则对子字符串中字符的更改将在稍后的其他字符串中反映出来。

Concurrency: If the internal structure of an immutable object is valid, it will always be valid. 并发:如果不可变对象的内部结构有效,它将始终有效。 There's no chance that different threads can create an invalid state within that object. 不同的线程不可能在该对象中创建无效状态。 Hence, immutable objects are Thread Safe . 因此,不可变对象是线程安全的

Garbage collection: It's much easier for the garbage collector to make logical decisions about immutable objects. 垃圾收集:垃圾收集器更容易对不可变对象做出逻辑决策。

However, there are also downsides to immutability: 但是,不变性也有缺点:

Performance: Wait, I thought you said performance was an upside of immutability! 表现:等等,我以为你说性能是不变的好处! Well, it is sometimes, but not always. 嗯,有时候,但并非总是如此。 Take the following code: 请使用以下代码:

foo = foo.substring(0,4) + "a" + foo.substring(5);  // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder

The two lines both replace the fourth character with the letter "a". 这两行都用字母“a”替换第四个字符。 Not only is the second piece of code more readable, it's faster. 第二段代码不仅更具可读性,而且速度更快。 Look at how you would have to do the underlying code for foo. 看看你将如何为foo做底层代码。 The substrings are easy, but now because there's already a character at space five and something else might be referencing foo, you can't just change it; 子串很容易,但现在因为在第五空间已经有了一个字符而其他东西可能引用了foo,你不能只改变它; you have to copy the whole string (of course some of this functionality is abstracted into functions in the real underlying C, but the point here is to show the code that gets executed all in one place). 你必须复制整个字符串(当然,这些功能中的一些被抽象为真正底层C中的函数,但这里的重点是显示在一个地方执行的代码)。

struct String* concatenate(struct String* first, struct String* second)
{struct String* new = malloc(sizeof(struct String));new->length = first->length + second->length;new->characters = malloc(new->length);int i;for(i = 0; i < first->length; i++)new->characters[i] = first->characters[i];for(; i - first->length < second->length; i++)new->characters[i] = second->characters[i - first->length];return new;
}// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));

Note that concatenate gets called twice meaning that the entire string has to be looped through! 请注意,连接被调用两次意味着整个字符串必须循环通过! Compare this to the C code for the bar operation: 将其与bar操作的C代码进行比较:

bar->characters[4] = 'a';

The mutable string operation is obviously much faster. 可变字符串操作显然要快得多。

In Conclusion: In most cases, you want an immutable string. 结论:在大多数情况下,您需要一个不可变的字符串。 But if you need to do a lot of appending and inserting into a string, you need the mutability for speed. 但是如果你需要做很多追加和插入字符串,你需要速度的可变性。 If you want the concurrency safety and garbage collection benefits with it the key is to keep your mutable objects local to a method: 如果您希望并发安全和垃圾收集带来好处,关键是将可变对象保持在方法的本地:

// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{StringBuilder mutable;boolean first = true;for(int i = 0; i < strings.length; i++){if(!first) first = false;else mutable.append(separator);mutable.append(strings[i]);}return mutable.toString();
}

Since the mutable object is a local reference, you don't have to worry about concurrency safety (only one thread ever touches it). 由于mutable对象是本地引用,因此您不必担心并发安全性(只有一个线程会触及它)。 And since it isn't referenced anywhere else, it is only allocated on the stack, so it is deallocated as soon as the function call is finished (you don't have to worry about garbage collection). 并且由于它没有在其他任何地方引用,它只在堆栈上分配,所以一旦函数调用完成就会释放它(你不必担心垃圾收集)。 And you get all the performance benefits of both mutability and immutability. 并且您可以获得可变性和不变性的所有性能优势。


#3楼

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最佳实践。


#4楼

Immutable means that once the object is created, non of its members will change. 不可变意味着一旦创建了对象,其成员就不会改变。 String is immutable since you can not change its content. String是不可变的,因为您无法更改其内容。 For example: 例如:

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创建的。


#5楼

"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的关键然后改变值会发生什么(提示:想想equalshashCode )。


#6楼

一个含义与值如何存储在计算机中有关,例如,对于.Net字符串,这意味着内存中的字符串无法更改,当您认为正在更改它时,您实际上正在创建一个新的字符串在内存中并将现有变量(它只是指向其他地方的实际字符集合的指针)指向新字符串。

不可变的意思是什么?相关推荐

  1. CVPR2020:点云分析中三维图形卷积网络中可变形核的学习

    CVPR2020:点云分析中三维图形卷积网络中可变形核的学习 Convolution in the Cloud: Learning Deformable Kernels in 3D Graph Con ...

  2. Python 函数的可变参数(*paramter与**paramter)的使用

    Python 函数的可变参数主要有 *paramter与**paramter 可变参数主要有 *paramter的作用 接受任意多个实际参数并放到一个元组中 def people(*people):f ...

  3. Python 精选笔试面试习题—类继承、方法对象、包管理、闭包、可变类型作为默认参数、列表引用、sort与sorted、 append 和 extend、深拷贝和浅拷贝

    1. 类继承 如下代码 class A(object):def show(self):print 'This is calss A'class B(A):def show(self):print 'T ...

  4. 具体解释可变參数列表

    可变參数   至少有一个參数 比如:void add(int a,- ){} 例题  模拟printf()函数 #include <stdio.h> #include <stdarg ...

  5. c语言 可变参数的宏,可变参数的宏__ VA_ARGS__的用法

    回顾 在[ANSIC几种特殊的标准定义]中我们讲述了比较常用的几项: __FILE__:正在编译文件的路径及文件名 __LINE__:正在编译文件的行号 __DATE__:编译时刻的日期字符串 如&q ...

  6. Python:python中的可变类型和不可变类型

    Python的基本数据类型大致可分为6类: 1.Number(数字)(bool布尔类型.int整型.float浮点型.complex复数等都归为Number数字类型) 2. String(字符串) 3 ...

  7. java string改变的影响_为什么Java的string类要设成immutable(不可变的)

    最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类 ...

  8. python哪些是可变对象_python的不可变对象与可变对象及其妙用与坑

    先上图. 图里,分别用三个整数进行了验证.可以发现当a和b值相同时,a与b地址也一致.改变a的值,a的地址也跟着改变了. 原因 python的宗旨之一,万物皆对象.(单身狗狂喜) 而对象又被分为可变对 ...

  9. python可变序列和不可变序列_一文看懂可变序列和不可变序列

    先说点概念 在解释可变/不可变序列之前,先要知道什么是序列?序列就一个个元素有序地排列在一起,像小朋友"排排坐,吃果果"一样. 可变序列就是创建一个序列后,可以改变元素,可以比如成 ...

  10. iOS 实现多个可变 cell 复杂界面的制作

    来源:飘游人 www.jianshu.com/p/9fc838d46f5e 如有好文章投稿,请点击 → 这里了解详情 在日常的开发中,有时会遇到内容块比较多,且又可变的界面: 这个界面中有些内容块是固 ...

最新文章

  1. 蜻蜓resin服务器虚拟目录的设置
  2. OpenStack 系列之File Share Service(Manila)详解
  3. 非空约束对数据更新的影响
  4. 当前最好的非深度迁移学习方法:流形空间下的分布对齐
  5. JavaScript入门(part2)--JS书写方式及注释
  6. 跟我学《JavaScript高程3》第一讲,视频课程,课程笔记
  7. HP5200打印机从控制面板手动配置TCP/IP 参数
  8. Stream将List转换为Map
  9. php 5.5.1,PHP5.3.1 不再支持ISAPI
  10. php 实现资料下载功能,学习猿地-php如何实现下载功能
  11. C++常用基础函数整理
  12. 怎样才能容易更换DB
  13. Stuck Stack成过去时,OpenStack升级还可以这样玩?!
  14. 西安适合计算机专业的研究所,计算机类专业比较厉害的6所大学,适合于中等偏上的学生报考...
  15. django.template.exceptions.TemplateSyntaxError: Invalid block tag on line 12: ‘static‘. Did you forg
  16. linux主机motd和命令审计
  17. Python拆分PPT文件的方法
  18. NPN三极管放大原理
  19. eden区分配至s0、s1
  20. Android.mk编译java动态库

热门文章

  1. android studio 导入、移除module、以及加载module中的jar包
  2. Activity启动流程
  3. Android JetPack ViewModel 源码解析
  4. 算法------数组---------存在重复元素
  5. matlab均值量化函数_在matlab中理解抽样量化的概念:均匀量化的实现
  6. 深入浅出换肤相关技术以及如何实现
  7. 打开Eclipse时出现Failed to create the Java Virtual Machine
  8. 精益创新之设计思维研磨——《设计改变一切》书评
  9. JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]
  10. java 常见几种发送http请求案例