欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

7月26日讨论关于String的不可变性质。

程序员文章站 2022-06-19 11:54:23
前几天和朋友相互面试(为了秋招作准备),然后它问了我一个问题,说说String和StringBuffer以及StringBuilder之间的区别。我回答的很官方,也可以说很浅显吧,因为关于那三者之间的联系和区别我也确实没有深究,知识按照面经题目上理解了三者的性质。String类是用final修饰,然后它底层是用final private char[] value实现的,所以它是不可变的,而StringBuffer由于用了锁机制所以它是线程安全的,StringBuilder由于没有用锁来约束,所以它是线程...

前几天和朋友相互面试(为了秋招作准备),然后它问了我一个问题,说说String和StringBuffer以及StringBuilder之间的区别。

我回答的很官方,也可以说很浅显吧,因为关于那三者之间的联系和区别我也确实没有深究,知识按照面经题目上理解了三者的性质。String类是用final修饰,然后它底层是用final private char[] value实现的,所以它是不可变的,而StringBuffer由于用了锁机制所以它是线程安全的,StringBuilder由于没有用锁来约束,所以它是线程不安全的,但也由于它没有用锁,所以它的性能要优于String和StringBuffer。

如果面试的时候这么答确实也没啥问题(前提是面试官不继续深究问下去)。

然后朋友又问了为什么说String是不可变的呢?

我说因为它用final修饰了哇。

然后他又问,难道用final修饰了就是不可变了吗?

我竟无言以对,然后他说因为String是final修饰的,所以String创建的对象是不可变的,但String创建的引用变量是可以改变的,它可以重新指向其他的对象。

听完他的解释我总感觉哪儿不对,但因为毕竟理解的不到位,所以也不好反驳他。

所以今天晚上我特意抽时间去查了一下相关资料,但是我发现网上的资料对这方面的解释并不是很到位,他们的解释也是停留在,那种很标准的回答上,即由于String类本身是final修饰的,而且它底层的数组也是final修饰的,所以它是不可变的。

然后举个栗子:

7月26日讨论关于String的不可变性质。

其中一个老哥是这样解释String的不可变性的。虽然他的解释理论上没啥问题,但是感觉看了他的解释我的疑惑进一步加深了,因为说String是不可变类型,但是String类型的变量却可以随意指向其他的对象(这一点其实还好)。最让我无法理解的是:这个引用不断可以随意指向其他变量,还可以随意改变地址。

最后想了很久,终于想通了,之所以说String类型的对象是不可变的,它实际上是说String的实例化对象

例如String s = new String("加油");

这个例子中new String("加油")创建并实例化了一个“加油”的String类型的变量,并且用引用类型的变量指向了“加油”这个String对象。所以此处的不可变只是“加油”不可变,而引用类型的变量s随便你怎么变没什么关系。

而为什么“加油”这个实例化的String类型的对象为什么是不可变的呢?我觉得这个和private final char value[]没什么关系。而主要原因是final关键字修饰了String这个类。下面看看String这个类的数据结构:

7月26日讨论关于String的不可变性质。

下面看看java中对不可变类的解释:

不可变类只是其实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例的时候就提供,并且在对象的整个生命周期内固定不变。为了使类不可变,要遵循下面五条规则:

1.不要提供任何修改对象状态的方法。

2.保证不会被扩展。一般的做法是让这个类称为final的,防止子类化,破坏该类的不可变行为。

3.使得所有的域都是final的。

4.使得所有的域都成为私有的。方式客户端获得访问被域引用的可变对象的权限,并防止客户端直接修改这些对象。

5.确保对于任何可变性组件的互斥访问。如果类具有指向可变对象的域,则必须确保该类的客户端无法指向这些对象的引用。

下面是我进行的一些实验:

7月26日讨论关于String的不可变性质。

7月26日讨论关于String的不可变性质。

本文地址:https://blog.csdn.net/qq_34473178/article/details/107599646