跟大佬展开激励讨论String的不可变性
创始人
2024-04-25 11:21:59
0

 

目录

大佬证明:

我的证明:

后续

什么是不可变?

String为什么不可变

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

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

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

String真的不可变吗?


ps:事情是这样的,前段时间跟一位大佬随口提了一嘴String的不可变的原因,也是比较浅的说了一嘴,都没有放心上。过了几天大佬给我发消息过来说他翻找了一下他之前的笔记,对于String不可变的关键原因final才是不可变的关键,这一下激起来我的兴趣,于是我们各持观点展开了“辩论赛”,首先我们来看一下Java源码

 我们可以看到String类中有两个属性,分别为value数组与hash,其中value数组是被private final所修饰的,我们的观点产生了分歧,大佬所持的观点是final是String不可变的关键,我所持的观点是private是String不可变的关键

大佬证明:

 随后大佬问了我一个这样的问题,当这么定义的时候,str1==str2输出的结果

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

我大概看了一下,想到只要是变量就会开辟栈帧,对于对象引用之间比较的是地址,所以输出false;肯定是错了,我忘记了他们指向的都是常量池中同一个对象。如此一来,我直接落入下风,大佬趁势继续提了一个问题

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

这个我答对了 是false,回答出这个问题我才想到我之前上个问题回答错了;随后我便要开始狡辩了~

我的证明:

首先我给大佬看了这个图

 看完之后我们突然发现~讨论的问题尺度偏了,但是这也正好展现出了String类在JVM中存储的简图,再回到我们之前的问题后,我开始了我的证明,我的观点是:

final修饰类表明该类不可以被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的,所以final不是String不可变的关键原因,为何说private是String不可变的关键原因,是因为private是封装的意思,被private修饰后,类外无法访问到,并且String类中也没有提供到任何可以用来修改value数组中值的方法,所以才造成String不可变

后续

大佬听完我的观点后,之后一起去查阅资料发现了真正原因


什么是不可变?

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

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


String为什么不可变

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

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

我们来看一下以下例子

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

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

1)首先,char 数组是 private 的,并且 String 类没有对外提供修改这个数组的方法,所以它初始化之后外界没有有效的手段去改变它;

2)其次,String 类被 final 修饰的,也就是不可继承,避免被他人继承后破坏;

3)最重要的!是因为 Java 作者高斯林老爷子String 的所有方法里面,都很小心地避免去修改了 char 数组中的数据,涉及到对 char 数组中数据进行修改的操作全部都会重新创建一个 String 对象。

4)所以说,对于String不可变的解释,我们可以说两者都是缺一不可的,两者是互相搭配,final和private 都影响了


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

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中有一种反射的手段,反射是什么意思呢,大概给大家来一张图理解一下

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

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

那么我们看如下代码

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

相关内容

热门资讯

安卓系统新消息弹屏,体验升级 你知道吗?最近安卓系统又来了一大波新消息,这可真是让人兴奋不已!想象当你正在专心致志地刷着手机,突然...
刷机原生安卓系统,体验纯净流畅 你有没有想过,你的手机其实可以像新的一样?没错,就是那种刚从店里拿出来,充满活力的感觉。今天,就让我...
平板安卓系统升级安装,轻松实现... 亲爱的平板用户们,是不是最近你的安卓平板突然弹出了系统升级的提示,让你有点小激动又有点小紧张呢?别急...
安卓系统支持杜比吗,杜比音效技... 你有没有想过,你的安卓手机里那些美妙的音乐和电影,是不是也能享受到杜比音效的震撼呢?没错,今天咱们就...
安卓系统有哪些游戏,热门游戏盘... 你有没有发现,手机里的游戏世界简直是个宝藏库啊!尤其是安卓系统,那简直就是游戏爱好者的天堂。今天,就...
游戏苹果转换安卓系统,轻松实现... 你有没有想过,把你的苹果手机上的游戏转到安卓系统上玩呢?这听起来是不是有点像一场说走就走的旅行?别急...
安卓系统更新设置停止,节省流量 亲爱的安卓用户们,你是否也有过这样的经历:每次安卓系统更新后,总是迫不及待地想要体验新功能,却发现更...
安卓系统基础设置在哪,生成个性... 亲爱的手机控们,你是不是在安卓手机上翻来覆去,就是找不到那个神秘的“基础设置”按钮?别急,今天我就来...
安卓实时获得系统时间,安卓系统... 你有没有想过,你的安卓手机是怎么知道现在是什么时间的呢?是不是觉得这事儿很简单,不用多想?其实,这里...
安卓刷英菲克系统,安卓系统升级... 你有没有想过,你的安卓手机或者平板,是不是也能装上英菲克系统呢?听起来是不是有点不可思议?别急,今天...
安卓系统能玩的fc游戏,重温童... 你有没有想过,那些小时候陪伴我们度过无数欢乐时光的FC游戏,现在竟然可以在安卓系统上重温呢?没错,就...
安卓系统外放音量调节,享受个性... 你有没有遇到过这种情况:手机里的音乐或者视频播放得正high,突然音量突然变得超级小,让你差点没听清...
安卓系统升级多少流量,每级升级... 你有没有发现,每次安卓系统一升级,手机里的流量就像被吸走了一样,瞬间感觉不够用呢?别急,今天就来给你...
安卓系统笔记本音量,探索智能音... 你有没有遇到过这种情况:拿着你的安卓系统笔记本,正沉浸在某个精彩的电影或者游戏中,突然音量太小,让你...
华为安卓系统经典型号,引领科技... 你有没有想过,手机的世界里,有些型号就像明星一样,无论时代怎么变迁,都依然闪耀着独特的光芒?今天,就...
55英寸安卓系统,畅享科技与娱... 你有没有想过,家里的电视该升级换代了?别急,今天就来给你好好聊聊55英寸安卓系统的电视,看看它到底有...
全民k系统安卓版下载,一键下载... 你有没有听说最近超级火的全民K系统安卓版下载?没错,就是那个让无数手机用户为之疯狂的系统!今天,我就...
手机中的安卓系统,手机智能生活... 你有没有发现,现在手机里的安卓系统就像是个万能的小助手,无处不在,无所不能呢?它就像是我们生活中的得...
gm8系统是安卓系统吗,安卓生... 你有没有听说过GM8系统?最近这个话题在数码圈里可是挺火的。很多人都在问,GM8系统是安卓系统吗?今...
安卓系统文件非常大,揭秘庞大文... 你有没有发现,最近你的安卓手机越来越卡了?别急,别急,让我来给你揭秘一下这个谜团。没错,就是那个让我...