在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年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...
随机推荐
- 解决GitHub下载速度比较慢
第一步,打开本机上的Hosts文件 首先,什么是Hosts文件? 在互联网协议中,host表示能够同其他机器互相访问的本地计算机.一台本地机有唯一标志代码,同网络掩码一起组成IP地址,如果通过点到点协 ...
- 随机重拍与抽样(random_shuffle,random_sample,random_sample_n)
//版本一:使用内部的随机数生成器 template<class RandomAccessIterator> void random_shuffle( RandomAccessIterat ...
- 谈谈 在 .Net 生态里为什么没有 Hadoop 系列 ?
在 .Net 生态里为什么没有 Hadoop 系列 ? 有需要 有 Hadoop 系列 吗 ?
- Delphi Json之树遍历
procedure TForm1.VisitDirJsonTree(const AJsonObj: ISuperObject); var i: Integer; oItem: TSuperAvlEnt ...
- TypeScript 知识点
TypeScript 通过 类型批注 提供静态类型以在编译时启动类型检查. 基本批注类型是number.bool.string.而弱或动态类型是any. typescript 使用 作用 语句 全局安 ...
- DevExpress GridView 那些事儿
1:去除 GridView 头上的 "Drag a column header here to group by that column" --> 点击 Run Desig ...
- unicodedata.normalize()/使用strip()、rstrip()和lstrip()/encode和decode 笔记(具体可看 《Python Cookbook》3rd Edition 2.9~2.11)
unicodedata.normalize()清理字符串 # normalize()的第一个参数指定字符串标准化的方式,分别有NFD/NFC >>> s1 = 'Spicy Jala ...
- MeshLab显示纹理贴图
共需要三个文件:obj文件.mtl文件及一张纹理图. 1.obj文件需要满足如下格式: 顶点 v 纹理坐标 vt 法线 vn 面片f Vertex1/Texture1/Normal1 Vertex2/ ...
- html-display标签
标签可以分为行内标签和行间块级标签, 块级标签:占一行,如果父标签没有限高度,子标签会自动扩展父标签的高度,行内标签不能, 可以设置宽度 高度 padding margin 行内标签: 不能设置 ...
- 《LOST》 电视
还没看正剧,所以转来帮助看电视 从起源到终点:<LOST>剧情全解析(一) 此文是LOST完结之后的剧情解析,剧透,慎入 从起源到终点:<LOST>剧情全解析(一) 转 ...