String的不可变性设计原理

01 什么是不可变性

    不可变是指对象的属性被赋值后就不能变了
    也就是说String类的属性被构造方法初始化之后就没有其他的办法进行修改了

02 String是如何被设计为不可变的

在创建对象的时候只能通过构造方法的形式,不能通过set方法
在这里插入图片描述


当构造方法是空时,对应的构造方法源码是下面的,等于是 空的字符串
在这里插入图片描述


当使用带参数的构造方法时,带参构造方法源码
在这里插入图片描述


上面的代码可以看到都是把构造方法中的参数给了String类的char类型的数组
在这里插入图片描述


1 char类型的数组是private的,不能在类外部调用修改
2 char类型的数组是final的,引用地址不能变
3 没有提供set()方法来修改字符串的值
4 类声明为final不允许继承 子类就不能修改
也就是说String类的属性被构造方法初始化之后就没有其他的办法进行修改了

03 为什么被设计为不可变

   (1)  字符串常量池的需要 
          只有当字符串是不可变的,字符串池才有可能实现。因为多个字符串引用都指向常量池中的同一个字符串常量对象。但如果字符串是可变的,其中有一个引用改变了它的值,那么其它引用变量的对象值也会一起改变 ,就会引起错误
   (2)  hashcode缓存的需要  
            因为字符串不可变,所以在它创建时hashcode就被缓存了,不需要重新计算。这就使得字符串很适合作为HashMap或hashSet中的key,效率高。字符串处理速度要快过其它的键对象
   (3)  多线程安全
          多线程中,可变对象的值很可能被其他线程改变,造成不可预期的结果。而不可变的String可以自由在多个线程之间共享,不需要同步处理
     (4)  安全问题
        如果字符串是可变的,那么会引起很严重的安全问题。如,数据库的用户名、密码都是以String的形式传入来获得数据库的连接,或者在 socket 编程中,主机名和端口都是以字符串的形式传入。因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞

      类加载器要用到字符串,不可变性提供了安全性,以便正确的类被加载。譬如你想加载 java.sql.Connection 类,而这个值被改成了 myhacked.Connection ,那么会对你的数据库造成不可知的破坏

     安全首要原因是安全,不仅仅体现在你的应用中,而且在JDK中,Java的类装载机制通过传递的参数(通常是类名)加载类,这些类名在类路径下,想象一下,假设String是可变的,一些人通过自定义类装载机制分分钟黑掉应用。如果没有了安全,Java不会走到今天

04 体现不可变性质

两个指向指向同一个字面值 其中一个进行修改 另外一个还是以前的值

在这里插入图片描述

输出
a
b

使用replace()等时 生成新的自传 以前的字符串不会变
在这里插入图片描述

输出
bbc

问题

这段代码执行后 原始string对象中的内容变了吗
在这里插入图片描述

 没有
 String被设计成不可变类,它的所有对象都是不可变对象  string原先指向"a"对象,然后对string进行了+操作 这时string不再指向原来那个对象了,而指向了"ab"对象,原来那个对象还存在于内存之中,只是string这个引用变量不再指向它了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值