0
点赞
收藏
分享

微信扫一扫

跟大佬展开激励讨论String的不可变性

树下的老石头 2022-12-18 阅读 200

 

目录

大佬证明:

我的证明:

后续

什么是不可变?

String为什么不可变

为什么要设计成为不可变的呢? 

1.首先我们最先可以想到的Java主要做的就是安全

2.其次是字符串常量池的需要

String真的不可变吗?



什么是不可变?

        对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。这就意味着,一旦我们将一个对象分配给一个变量,就无法再通过任何方式更改对象的状态了

String 不可变的表现就是当我们试图对一个已有的对象 "abcd" 赋值为 "abcde",String 会新创建一个对象,从而引用其他对象;


String为什么不可变

        String中的value属性被final所修饰,这个数组无法被修改,这么说确实没啥问题。

但是!!!这个无法被修改仅仅是指引用地址不可被修改(也就是说栈里面的这个叫 value 的引用地址不可变,编译器不允许我们把 value 指向堆中的另一个地址),并不代表存储在堆中的这个数组本身的内容不可变

我们来看一下以下例子

 但是我们如果仅仅改变数组中的值,如下是可以的

那既然说String是不可变的,那显然仅仅靠final支撑是不够的


为什么要设计成为不可变的呢? 

1.首先我们最先可以想到的Java主要做的就是安全

        然而private就是为了安全所诞生的,这也更加体现出private是不可缺少的,作为最基础最常用的数据类型,String 被许多 Java 类库用来作为参数,如果 String 不是固定不变的,将会引起各种安全隐患。

2.其次是字符串常量池的需要

        为什么会存在字符串常量池呢?它所存在的意义是什么呢?大量频繁的创建字符串,将会大大的影响程序的性能,为此,JVM 为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化

  • 为字符串开辟了一个字符串常量池 String Pool,可以理解为缓存区
  • 创建字符串常量时,首先检查字符串常量池中是否存在该字符串
  • 若字符串常量池中存在该字符串,则直接返回该引用实例,无需重新实例化;若不存在,则实例化该字符串并放入池中。

我们可以将之前的代码再拿出来看看

public static void main (String[] args) {
        String str1="hello";
        String str2="hello";
        System.out.println(str1==str2);
}

为什么他们会使true呢?因为他们共同指向了常量池中的“hello”所在的地址,假设我们的String是可以变的,那么我们通过修改str2=“world”; 那么我们的str1中所指向的内容也会被改变,这显然不是老爷子设计Java之初,也不是我们想要看到的


String真的不可变吗?

        想要改变 String 无非就是改变 char 数组 value 的内容,而 value 是私有属性,那么在 Java 中有没有某种手段可以访问类的私有属性呢?

我们Java中有一种反射的手段,反射是什么意思呢,大概给大家来一张图理解一下

假设我们帅气的博主今天去过安检,带着一个行李箱,行李箱中装着一把加特林

 那么我们肯定是过不去安检的啦,安检会发现我们在行李箱中的加特林,反射就类似于安检机。

那么我们看如下代码

 如此一来便做到了修改值,所以说这个跟安全也是互斥的~至于为什么设计,那就不得而知了,可能老爷子有着自己的想法~

举报

相关推荐

0 条评论