聊聊JAVA中 String类为什么不可变
前言
"我的风格比较偏传统和经典" 小明说,"我们在打扮自己的问题上还是蛮冒险的...我觉得当你是只狗的时候,穿什么都hold的住!"

哈哈哈,脱离单身狗快两年了,生活中除了爱情,不变的还有对代码的挚爱,总之始于热爱,忠于爱情,陷于代码。
前半年规划人生,后半年开始规划,最近发生的一些事情还是让自己倍感压力的,生活可以知足常乐,但人生不可以,如果你不把生命体验到极致,也许会被未来的自己所鄙视。
前世今生
String不可变这个话题应该是老生长谈了,你可以说它就是设计者的龟腚,然后巴拉巴拉说出一大堆优点,也可以说它忠于爱情,只要JVM存活,它便万年不变。
String自打娘胎一出生就跟他们的兄弟姐妹不一样,好好的娃被戴了一个final的帽子,以至于byte,int,short,long等基本类型的小伙们都不带它玩。
但是,String并不是一个简单的人设,如果各位小伙伴们仔细查阅其源码,那可是浩浩荡荡的3000+行代码了,如果你一个controller能这样的代码量也是非常不错的。
如果你仔细阅读源码注释,你会发现这样一句话:
Strings are constant; their values cannot be changed after they are created
大致意思就是String是个常量,从一出生就注定不可变。
我觉得到这里各位小伙们应该就知道为什么String不可变了,戴了个final的帽子,官方注释说明创建后不能被改变,但是为什么String要使用final修饰呢?
面试精选
在了解String不可变之前,我觉得有必要分析一道经典的面试题:
public class Apple {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a==b);
System.out.println(a.equals(b));
System.out.println(a==c);
System.out.println(a.equals(c));
}
}
答案是:true、true、false、true
如图所示,代码中的abc对应个的abc:

我觉得有必要把a、b、c替换成小明、红、光,abc替换成红苹果重新梳理一下流程:
小明想吃红苹果,小明的爸爸首先会在树上寻找是否有红苹果,有的话,爸爸就说,这个苹果归你了,如果没有,假设万能的小明爸爸也可以给他造一个。
这时候小红过来了,爸爸我也想吃那个红苹果,并且强烈要求要拿一个,就这样小明和小红共享了这个苹果。
小光是个听话的孩子,只要是红苹果就行,我可不想跟他俩争什么,爸爸就这样从超市里给小光买了一个红苹果。
小明和小红的是同一个苹果,这个是不变的事实,无论你怎么比较。
小红,小明和小光的都是红苹果,但却不是同一个苹果。
你可以把苹果树理解成常量池,爸爸购买苹果的过程理解为new对象,当然,举例可能不是太恰当,只是为了大家更好的理解。
回到代码本来来说,因为String太过常用,JAVA类库的设计者在实现时做了个小小的变化,即采用了享元模式,每当生成一个新内容的字符串时,他们都被添加到一个共享池中,当第二次再次生成同样内容的字符串实例时,就共享此对象,而不是创建一个新对象,但是这样的做法仅仅适合于通过=符号进行的初始化。
需要说明一点的是,在object中,equals()是用来比较内存地址的,但是String重写了equals()方法,用来比较内容的,即使是不同地址,只要内容一致,也会返回true,这也就是为什么a.equals(c)返回true的原因了。
不可变的好处
首先,我们应该站在设计者的角度思考问题,而不是觉得这不好,那不合理:
可以实现多个变量引用堆内存中的同一个字符串实例,避免创建的开销。
我们的程序中大量使用了String字符串,有可能是出于安全性考虑。
大家都知道HashMap中key为String类型,如果可变将变的多么可怕。
当我们在传参的时候,使用不可变类不需要去考虑谁可能会修改其内部的值,如果使用可变类的话,可能需要每次记得重新拷贝出里面的值,性能会有一定的损失。
其次,我们再分析有没有更好的解决方案:
- 然,对于我来说,并没有!!!
- 然,对于我来说,并没有!!!
- 然,对于我来说,并没有!!!
总结
了解到String是不可变的,知道了常量池是怎么个东西。
重温了面试题,有兴趣的小伙伴也可以去阅读下String的源码,浩浩荡荡的3000+。
String 被new时是要创建对象的,+ 号拼接同理,程序中尽量不要使用 + 拼接,推荐使用StringBuffer或者StringBuilder。
聊聊JAVA中 String类为什么不可变的更多相关文章
- java中String类为什么不可变?
在面试中经常遇到这样的问题:1.什么是不可变对象.不可变对象有什么好处.在什么情景下使用它,或者更具体一点,java的String类为什么要设置成不可变类型? 1.不可变对象,顾名思义就是创建后的对象 ...
- 在java中String类为什么要设计成final?
大神链接:在java中String类为什么要设计成final? - 程序员 - 知乎 我进行了重新排版,并且更换了其中的一个例子,让我们更好理解. String很多实用的特性,比如说“不可变性”,是工 ...
- Java中String类为什么被设计为final?
Java中String类为什么被设计为final 首先,String是引用类型,也就是每个字符串都是一个String实例.通过源码可以看到String底层维护了一个byte数组:private f ...
- Java中String类的方法及说明
String : 字符串类型 一. String sc_sub = new String(c,3,2); // String sb_copy = new String(sb) ...
- java中String类学习
java中String类的相关操作如下: (1)初始化:例如,String s = “abc”; (2)length:返回字符串的长度. (3)charAT:字符操作,按照索引值获得字符串中的指定字符 ...
- 在java中String类为什么要设计成final
在java中String类为什么要设计成final? - 胖胖的回答 - 知乎 https://www.zhihu.com/question/31345592/answer/114126087
- 【转载】Java中String类的方法及说明
转载自:http://www.cnblogs.com/YSO1983/archive/2009/12/07/1618564.html String : 字符串类型 一. String sc_ ...
- 在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?
最近突然被问到String为什么被设计为不可变,当时有点懵,这个问题一直像bug一样存在,竟然没有发现,没有思考到,在此总结一下. 1.String的不可变String类被final修饰,是不可继承和 ...
- Java中String为什么是不可变的
1.在Java中,String类是不可变类,一个不可变类是一个简单的类,并且这个的实例也不能被修改, 这个类的实例创建的时候初始化所有的信息,并且这些信息不能够被修改 2.字符串常量池 字符串常量池是 ...
随机推荐
- Linux sort命令中文手册(info sort翻译)
说明: (1).本手册只挑选了有用的信息进行翻译,如要查看完完整整的内容,请自行info sort. (2).译文中,在括号中使用了"注"的,为本人所加,非原文内容,助于理解和说明 ...
- 【win10】大水牛主机插入耳机没有声音
主机:大水牛,技嘉主板 操作系统:win10 问题:主机前面插入耳机,没有声音,扬声器图标出错 解决 一..插入耳机 二..Realtek高清晰音频管理器 1.打开音频管理器,点击右下角的设置 2.点 ...
- led模组的优点和却点
插件模组 1.是指DIP封装的灯将灯脚穿过PCB板,经由过程焊接将锡灌满在灯孔内,由这种工艺做成的LED模组便是插灯模组:益处是视角年夜,亮度高,散热好:谬误舛错是像素密度小. 表贴模组 1.表贴也叫 ...
- Win7电脑桌面的Administrator图标没了怎么办
Win7电脑桌面的Administrator图标没了怎么办.. win7电脑桌面的Administrator图标没了,怎么办?在桌面空白处右键选择个性化,进入个性化之后,左边栏选择“更改桌面图标”勾选 ...
- 菜单栏—View(视图)菜单
- Python+Requests接口测试教程(1):Fiddler抓包工具
本书涵盖内容:fiddler.http协议.json.requests+unittest+报告.bs4.数据相关(mysql/oracle/logging)等内容.刚买须知:本书是针对零基础入门接口测 ...
- thinkjs—控制器方法名不能大写
async updateInfoAction(){ ... } 上面的接口如果通过ajax访问,就会报404的错误.原因似乎在于访问updateInfo时,会自动转化成小写,而小写的updateinf ...
- java线程锁
一.synchronized 这货可以锁对象,锁变量,锁方法,锁代码,好像什么都能锁,缺点就是如果一个锁堵了,其他的只能等待忙并不能把当前的锁给释放.二. ReentrantLockR ...
- Vue.js入门指南(一)
前 言 JRedu 之前用过一段时间的AnglarJS 1.X,在低版本的AngularJS中,脏值检查在变量增多的情况下会影响程序的响应速度.后期的2.X和更高版本在脏值检查等问题上做了优化, ...
- java语言基础(变量和运算符)
java八大基本数据类型: 整型{ int(整型) short(短整型) long(长整型)} 浮点型{ float(浮点型) double(双精度)} 布尔{boolean} ...