在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?
最近突然被问到String为什么被设计为不可变,当时有点懵,这个问题一直像bug一样存在,竟然没有发现,没有思考到,在此总结一下。
1.String的不可变
String类被final修饰,是不可继承和修改的。当一个String变量被第二次赋值时,不是在原有内存地址上修改数据,而是在内存中重新开辟一块内存地址,并指向新地址。

String类为什么要被设计为是final的?
1.不可变性支持线程安全。
2.不可变性支持字符串常量池,提升性能。
3.String字符串作为最常用数据类型之一,不可变防止了随意修改,保证了数据的安全性。
正常情况下Java的String字符串是final且不可变的。不过可以通过特殊手段修改它的内容。
String类的主力成员字段value是个char[ ]数组,而且是用final修饰的。final修饰的字段创建以后就不可改变。因为虽然value是不可变,也只是value这个引用地址不可变。挡不住Array数组是可变的事实。Array的数据结构看下图:

也就是说Array变量只是stack上的一个引用,数组的本体结构在heap堆。String类里的value用final修饰,只是说stack里的这个叫value的引用地址不可变。没有说堆里array本身数据不可变。
代码测试:
String test = "immutable String";
String test1 = test;
String test2 = new String(test);
String test3 = new String(test.toCharArray());
Field values = String.class.getDeclaredField("value");
values.setAccessible(true);
char[] chars = (char[])values.get(test);
chars[] = 'u';
chars[] = 'n';
System.out.println("test==test1:" + (test == test1));
System.out.println("test==test2:" + (test == test2));
System.out.println("test1==test2:" + (test1 == test2));
System.out.println("test:" + test + " test1:" + test1 + " test2:" + test2 + " test3:" + test3);

由String的不可变性引申到其他基本数据类型: Byte,Short,Integer,Long,Double,Float,Character,Boolean 八种基本数据的包装类,仔细查看发现也是final修饰的,再仔细查看一下enum枚举类型,发现用javac编译后再用javap反编译也是被编译为final修饰的类,并且其枚举值全部定义为static final 修饰的成员变量。

由此发现,Java设计者在设计Java基本数据类型时,把基本数据类型全部设计为不可变的,这样既方便了开发人员,又保证了数据的安全性。
总结:Java中String是不可变的,但是可以通过反射修改其内容。
备注:
作者:Shengming Zeng
博客:http://www.cnblogs.com/zengming/
本文是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接。
<欢迎有不同想法或见解的同学一起探讨,共同进步>
在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?的更多相关文章
- 在java中String类为什么要设计成final
在java中String类为什么要设计成final? - 胖胖的回答 - 知乎 https://www.zhihu.com/question/31345592/answer/114126087
- 在java中String类为什么要设计成final?
大神链接:在java中String类为什么要设计成final? - 程序员 - 知乎 我进行了重新排版,并且更换了其中的一个例子,让我们更好理解. String很多实用的特性,比如说“不可变性”,是工 ...
- java中String类为什么要设计成final?
1 将方法或类声明为final主要目的是:确保它们不会在子类中改变语义.String类是final类,这意味着不允许任何人定义String的子类. String基本约定中最重要的一条是immutabl ...
- 【笔记】在java中String类为什么要设计成final?
部分内容转自知乎:https://www.zhihu.com/question/31345592 从自己的理解进行加工,压缩. String本质上是一个final类 public final clas ...
- Java中String类为什么被设计为final?
Java中String类为什么被设计为final 首先,String是引用类型,也就是每个字符串都是一个String实例.通过源码可以看到String底层维护了一个byte数组:private f ...
- java里String类为何被设计为final
前些天面试遇到一个非常难的关于String的问题,"String为何被设计为不可变的"?类似的问题也有"String为何被设计为final?"个人认为还是前面一 ...
- String类为什么被设计成不可变类
1.享元模式: 1.共享元素模式,也就是说:一个系统中如果有多处用到了相同的一个元素,那么我们应该只存储一份此元素,而让所有地方都引用这一个元素. 2.Java中String就是根据享元模式设计的,而 ...
- 【JAVA零基础入门系列】Day11 Java中的类和对象
今天要说的是Java中两个非常重要的概念--类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外观特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征 ...
- Java中的类反射
一.反射的概念 : 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...
随机推荐
- HotSpot VM GC 的种类
collector种类 GC在 HotSpot VM 5.0里有四种: incremental (sometimes called train) low pause collector已被废弃,不在介 ...
- vorpal 又一个方便的cli 开发包
vorpal 是一个npm 包,我们可以用来开发专业的cli 程序 简单使用 初始化项目 yarn init -y 添加依赖 yarn add vorpal 简单demo app.js // cons ...
- GBDT(Gradient Boosting Decision Tree) 没有实现仅仅有原理
阿弥陀佛.好久没写文章,实在是受不了了.特来填坑,近期实习了(ting)解(shuo)到(le)非常多工业界经常使用的算法.诸如GBDT,CRF,topic model的一些算 ...
- pycharm开发django项目 static报404解决方法
settings文件中确保有以下配置 # Static files (CSS, JavaScript, Images)# https://docs.djangoproject.com/en/1.10/ ...
- php格式化数字:位数不足前面加0补足
<?php $var=sprintf("%02d", 2);//生成2位数,不足前面补0 echo $var;//结果为02 ?> 參考:https://blog.cs ...
- Elasticsearch(四)优化用户体验
改正用户拼写 Term suggester:词项匹配建议:可以通过wiki的插件来下载wiki上面的单词以及短语,来作为你的拼写提示基础仓库: Phrase suggester:n-gram算法,短语 ...
- struts中的dojo控件sx:submit布局问题
想在一个四列的表格中插入两个按钮,希望实现下面的布局效果: 其中保存按钮为<sx:submit />控件.按照下面的代码布局: <tr><td align="c ...
- Tornado cookie 笔记
set_cookie()/get_cookie()的使用 def get(self): # self.get_cookie()获取cookie if not self.get_cookie('name ...
- Go RPC返回值
Go 语言RPC定义格式如下: func (t T) MethodName(argType T1, replyType T2) error 第一个参数是接收的参数,第二个参数是返回给客户端的参数,第二 ...
- 编译小米mini openwrt
编译小米mini openwrt 1.下载openwrt源码包:进入要下载保存的文件目录,输入 git clone git://git.openwrt.org/15.05/openwrt.git 2. ...