首页 > 编程知识 正文

stringbuilder为什么可变,java string为什么设计成不可变

时间:2023-05-03 12:02:29 阅读:283069 作者:2167

前言:可能快要线上考试了,本人刚刚开始复习0.0,理清了一些之前觉得有些混乱的概念,特在此分享一下自己的理解,希望也能帮到其他人

1.数据类型中的可变与不可变

我们知道,java中有可变数据类型和不可变数据类型之分,那么我们首先要理清,这里的变与不变指的是什么在变化或是保持不变?
在前面的博客中也有所总结,变化可以有两种:值的改变与引用的改变
很显然,这里的变化或是不变指的就是值的变化或是不变。
很简单的道理,我们可以拿String来分析,我们知道,String是不可变的数据类型,但你肯定写过类似的代码:

String s="Hey";s=s.concat(" Guys!");

这样的代码很显然是正确的,它没有违背String的不可变的特性,因为生成了一个新的字符串"Hey Guys!" ,而原来"Hey"字符串的值没有变,而仅仅是s字符串的引用发生改变:从指向"Hey"变为指向一个新的字符串"Hey Guys!"。因此数据类型中的变化是指“值的变化”。

2.final关键字

java中还提供了final关键字来提供额外的不可变,而这种不可变是针对引用的。笔者曾经并未考虑这些,直到今天复习才终于理清。
即被final修饰的变量,一经指定,就总是保持同一个引用,指向相同的地址空间,无论这个空间上的值是否发生改变。
如果将1中例子的s用final进行修饰,结果会是什么样呢?

final String s="Hey"; s=s.concat(" Guys!");

结果在编译时就会直接报错:

因为我们为s指定了新的引用,而这与final的约束相违背

3.可变数据类型的不可变引用

理清了1和2,我们接下来看看将final应用到可变数据类型会怎么样,先来理论上分析一下,这是完全行得通的,因为本身数据类型是值可变的,比如下面这段代码:

StringBuilder sb=new StringBuilder("a");sb.append("b");

这与1中String类型的例子非常相似,对于不可变数据类型String来说,其要保证每个字符串时不可变的,因此在末尾连接字符串的操作就会产生一个新的字符串。而对于可变数据类型StringBuilder来说,其值是可变的,因此可以在值"a"上直接连接"b",其变化的过程如图所示:

值的变化直接在同一个地址空间上就可以完成。但这时你还可以为他重新指定引用,让它指向新的地址。
那么理论上就可以为其加上final,实现引用不可变,即sb永远都只能指向图中所示的这一个地址,但在地址内部值是如何变化的,这就无法进行约束了。
像下面这段代码:

final StringBuilder sb = new StringBuilder("abc");//改变值sb.append("d");//改变引用sb = new StringBuilder("e");

前面的append是在保持引用的情况下改变其值,这是允许的,但用final修饰以后,后面sb = new StringBuilder(“e”);再想修改引用就会报错了:
为了验证,我们在两个变化后面都加上一条println语句:System.out.println(sb);进行打印,查看结果:

这里引用的改变提示错误


可以看到这里改变值的操作是成功的!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。