String的不可变特性

1、什么是不可变?
java语言要求不可变要遵循下面5点:
(1)、类内部所有字段都是final修饰的
(2)、类内部所有字段都是私有的,即private修饰的
(3)、类不能被继承或拓展
(4)、类不能对外提供能够修改内部状态的方法,setter方法也不行
(5)、类内部的字段如果是引用,也就是说可以指向可变对象,程序员不能获取这个引用
String就包含了上面5个特性。(第一点在严格意义上来说,并不是所有的字段都要是final修饰的,比如String中就包含了hash这个属性并没有由final修饰,这是因为String惰性计算hashCode存储在hash中(这是由于利用了String中其他的final类型的属性来保证每次hashCode的计算结果一样))。
ps:Integer等自动装箱类和String一样,但也有所不同,Integer只在值[-128,127]直接会直接去缓存中去读取。
2、String怎么被设计成不可变的?

public class Main01 {
    public static void main(String[] args) {
            String s = "s";
            System.out.println(s);
             s="d";
            System.out.println(s);            
    } 


这一段代码的输出结果:

不是说String是不可变的吗,怎么s的值变了?下面一个图能很好解释这个问题:
实际上是指向的地址变了,但是原来的指向地址的值并没有变,所以是满足String的不可变的。

下面看一下String的源码:

 public final class String
    implements Serializable, Comparable, CharSequence
{
        private final char value[];
        private int hash;
}

我们的String对象就是一个个字符存储在value数组里的,但是value没有set方法(value是由final修饰的),所以看着就是不可变的。数组也是引用传递
所以实际上起作用的是value,是value改变了引用。

3、为什么要将String设计成不可变的
(1)、提高字符串处理速度。在一个java项目中,String的使用是最多的,这就涉及到了增删改查,每次增删改查前jvm都会就检查String的安全性,就是通过hashCode,如果设计成了不可变的,就保证了每次的hashCode是唯一的。
(2)、节省空间。把字符串缓存起来,能够节省大量的堆空间,因为不同的字符串变量引用的是字符串常量池中的同一个对象。字符串常量池是java虚拟机用来存储字符串的特殊区域,由于String是不可变的,所以java虚拟机可以为同一个字符串只创建一个字符串副本,大大的节省了空间。
(3)、网络安全性。在网络连接和数据库连接中字符串常常作为参数,例如,网络连接地址URL,文件路径path,反射机制所需要的String参数。其不可变性可以保证连接的安全性。如果字符串是可变的,黑客就有可能改变字符串指向对象的值,那么会引起很严重的安全问题。
因为String是不可变的,所以它的值是不可改变的。但由于String不可变,也就没有任何方式能修改字符串的值,每一次修改都将产生新的字符串,如果使用char[]来保存密码,仍然能够将其中所有的元素设置为空和清零,也不会被放入字符串缓存池中,用字符串数组来保存密码会更好
(4)、线程安全。由于字符串是不可变的,因此可以在多线程之间共享,如果一个线程把字符串的值修改为另外一个,那么就会在字符串常量池中创建另外一个字符串,原有的字符串仍然会保持不变。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值