为什么要把Java字符串设计为不可变的
来源:互联网 发布:cf网截瞬移源码 编辑:程序博客网 时间:2024/05/16 17:38
String是Java中一个不可变的类,所以它一旦被实例化就无法被修改。不可变类一旦被创建就不可以被修改。本文将从内存、同步和数据结构相关知识简单说明一下将String设计为不可变类的好处。
(1)字符串池:
字符串池是方法区中一部分特殊存储。当一个字符串被创建的时候,首先会去字符串池中查找,如果找到,直接返回对该字符串的引用。
String str1 = "abcd";String str2 = "abcd";
这两个创建的引用都指向了同一个内存地址,在大量使用的情况下可以节省空间提高效率。最重要的是如果String是可变的话那么修改str2就会使得str1的值也发生改变,这不是我们希望看到的。
(2)String为什么不可变
在JDK源码中String类是被final修饰的,这就说明了String类不可以被继承。String本质上是一个char数组,而且也是用final修饰的。
//JDK部分源码public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[];
虽然value是不可变的,但也只是它的引用地址不可变,并不能改变它是一个Array数组的事实。也就是说虽然Array的引用地址不可变,但是Array中的数据是可以改变的。
final int[] value={1,2,3} int[] another={4,5,6}; value=another; //编译器报错,final不可变 //因为value使用final修饰的,不允许我就value的引用指向另一个堆区//但是如果直接修改里面的数值就是另外一回事了final int[] value={1,2,3}; value[2]=100; //这时候数组里已经是{1,2,100}//或者直接用反射直接修改final int[] array={1,2,3}; Array.set(array,2,100); //数组也被改成{1,2,100}
(3)不可变有什么好处
最直接的好处就是安全。String被广泛应用在其他Java类中充当参数。比如网络连接、打开文件等操作。如果字符串可变,那么类似操作可能会导致安全问题。因为某个方法在调用连接操作的时候,它认为会连接到某个机器上,但实际上没有(其它引用同一字符串的值修改会直接导致该字符串中内容的修改)。可变字符串也可能导致反射安全问题,因为他的参数也是字符串。
class Test{ public static void main(String[] args){ HashSet<StringBuilder> hs=new HashSet<StringBuilder>(); StringBuilder sb1=new StringBuilder("aaa"); StringBuilder sb2=new StringBuilder("aaabbb"); hs.add(sb1); hs.add(sb2); //这时候HashSet里是{"aaa","aaabbb"} StringBuilder sb3=sb1; sb3.append("bbb"); //这时候HashSet里是{"aaabbb","aaabbb"} System.out.println(hs); } } //Output: //[aaabbb, aaabbb]
StringBuilder型变量sb1和sb2分别指向了堆内的字面量”aaa”和”aaabbb”。把他们都插入一个HashSet。到这一步没问题。但如果后面我把变量sb3也指向sb1的地址,再改变sb3的值,因为StringBuilder没有不可变性的保护,sb3直接在原先”aaa”的地址上改。导致sb1的值也变了。这时候,HashSet上就出现了两个相等的键值”aaabbb”。破坏了HashSet键值的唯一性。所以千万不要用可变类型做HashMap和HashSet键值。
不可变对象天生就是线程安全的。在并发的场景下,多个线程去读一个资源时,不会出现什么问题,但是多个线程去写一个资源时就有危险。不可变对象不能被重写所以是安全的。
本内容部分参考原址
- 为什么要把Java字符串设计为不可变的
- 为什么Java要把字符串设计成不可变的
- 为什么Java要把字符串设计成不可变的
- 为什么 Java 要把字符串设计成不可变的
- 为什么 Java 要把字符串设计成不可变的
- 为什么Java要把字符串设计成不可变的
- 为什么Java要把字符串设计成不可变的
- 身为大神的你知道为什么Java要把字符串设计成不可变的嘛!
- 【String】为什么 Java 要把字符串设计成不可变的
- Java为什么把String设计成不可变的?
- 为什么Java的String设计为不可变的?
- 为什么Java中字符串被设计成不可变的?
- 为什么Java中字符串被设计成不可变的?
- Java要把字符串设计成不可变
- 首页所有文章资讯Web架构基础技术书籍教程我要投稿更多频道 » 为什么Java要把字符串设计成不可变的
- JAVA字符串为什么设计成不可变对象?
- 为什么spring要设计为不可变对象
- 为什么String被设计为不可变
- 计算机中分有符号数和无符号数
- 控制文字宽度进行显示内容-datagrid
- 兼容浏览器开发笔记-html标签编程注意事项
- svn密码地一直提示
- iOS 线程和进程的简单理解
- 为什么要把Java字符串设计为不可变的
- STM32F4应用笔记(六)UCGUI+uC/OS-II+支持触摸屏——触屏计算器
- Py GUI
- Python爬虫常用文档
- 【go语言读取mysql】go语言连接mysql,并且查询出结果
- nohub命令
- 点击下载文件、图片
- svn_差值更新
- call