String不可变?final修饰的变量不能变?

以下都是个人见解,如果有错误,希望能指出来,我会修改的。

【final】可修饰类,方法,变量。
如果修饰类,则该类无法被继承。
如果修饰方法,改方法无法被重写。
如果修饰的是基本数据类型变量,则该无法被赋予其他值。
如果是引用数据类型变量,那么得具体讨论。
例如String和StringBuffer。
在这里插入图片描述
在这里插入图片描述


【不可变】简单来说,当字符串一旦创建时,该字符串就不可改变。不可变指的是不可直接修改堆中内容(对象值不能改变),但可以修改栈中内容(引用地址可以改变)。

网友【wang_rh】的说法更加详细一些:
【不可变指的是不可直接修改堆中内容,但可以修改栈中内容(即可以修改引用)。即String t=new String(“abc”); t=“abcd”;修改的不是“abc”这个字面量。而是修改了t的引用(即栈中存储的内容)。所以代码执行后实际t已经不再是指向之前的对象了。】

例如:

// String s1="abc";
//s1="123";
这里,创建了对象"abc",引用s1指向对象"abc"。【不可变是指"abc"无法改变,但是引用s1是可以改变,即可以指向其他字符串对象,例如"123"。】

【String为什么不可变】在JDK14 java.lang.String 源码。
如下:

// String码源 其中的片段
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc {
    @Stable
    private final byte[] value;

String被final修饰,说明该类不可继承。
byte[] value被final修饰,说明value的引用在创建之后不能被改变。

// String s="abc";//以该代码为例,简单谈一下我个人的理解。

简单来说,解释Spring不可变就是解释"abc"是"abc",而无法变成"abcd"。

注意:不可变是指"abc"字符串创建后,【“abc"字符串】永远无法改变,不是指引用s永远指向"abc”。

①首先创建了一个byte[] 数组,把"abc"放入数组。数组一旦创建,类型和长度无法改变。
②value被final修饰,value是引用,value所指向的内存地址不可变(永远指向"abc"所在的byte[]数组),不可以指向其他对象。
三,value被private修饰,只能本类访问,无法被子类,同包等外部程序直接访问访问。
在这里插入图片描述
④有了保护性拷贝,不允许直接赋值给数组byte[],所以数组存储的是"abc"无法改变值。

【总结】value指向的地址无法改变,指向地址的对象类型无法改变,长度无法改变,对象的值无法改变。所以String是不可变的。

由于本人入门较晚,水平有限,如果有错误希望大佬能指出,为了照顾广大初学者,尽量解释的浅显易懂一些,十分感谢。


版权声明:本文为hqqkkc原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。