Java中的String为什么是不可变的?

什么是不可变对象?

       如果一个对象它被创建后,状态不能改变,则这个对象被认为是不可变的。也就是说,对象的地址,没有改变,我们就说,当前对象是不可改变的,对于引用型类型来说,用final修饰的,地址都是不可改变。

 

String是如何实现其对象不可变?

首先需要补充一个知识点:对于基本数据类型来说,用final修饰后,我们就说当前变量不能重新赋值,因此基本数据类型,是不可改变。但对于引用类型变量而言,它保存的仅仅是一个引用,final只保证这个引用变量所引用的地址不会改变,即一直引用同一个对象,但这个对象中成员变量或者数组完全可以发生改变。例如某个指向数组的final引用,它必须从此至终指向初始化时指向的数组,但是这个数组的内容完全可以改变。

       在java中,String保存值的两个重要成员变量,其中value指向的是一个字符串数组,字符串中的字符就是用这个value变量存储起来的,并且用final修饰,也就是说value一旦赋予初始值之后,value指向的地址就不能再改变了。虽然value指向的数组的值是可以改变的,但是String也没有提供相应的方法让我们去修改value指向的数组的元素。然而在StringBuilder中是提供了相应的方法让我们去修改value指向的数组的元素,这也是StringBuilder的字符串序列可变的原因。可见图如下:

 

Java中的String为什么是不可变的?_第1张图片

 

具体实例,并且配图分析:

Java中的String为什么是不可变的?_第2张图片

 

运行结果:

Java中的String为什么是不可变的?_第3张图片

 

程序分析:

       str1+=str2实际上是执行了str1=(new StringBuilder()).append(str2).toString();前后实际额外产生了一个StringBuilder与一个HelloWord的字符串常量。str1执行+=前后内存的示意图如下所示:
 

 

Java中的String为什么是不可变的?_第4张图片

 

 

Java中的String为什么是不可变的?_第5张图片

 

String对象真的不可变吗?

    虽然value是final修饰的,只是说明value不能再重新指向其他的引用。但是value指向的数组可以改变,一般情况下我们是没有办法访问到这个value指向的数组的元素。但是可以使用反射,可以反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。
 

 String str = "Hello World";
        System.out.println("修改前的str:" + str);
        System.out.println("修改前的str的内存地址" + System.identityHashCode(str));
        // 获取String类中的value字段
        Field valueField = String.class.getDeclaredField("value");
        // 改变value属性的访问权限
        valueField.setAccessible(true);
        // 获取str对象上value属性的值
        char[] value = (char[]) valueField.get(str);
        // 改变value所引用的数组中的字符
        value[3] = '?';
        System.out.println("修改后的str:" + str);
        System.out.println("修改前的str的内存地址" + System.identityHashCode(str));
 

String面试真题

String StringBuffer 的区别? 【基础】

JAVA 平台提供了两个类:String 和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String 类提供了数值不可改变的字符串。而这个StringBuffer 类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers 来动态构造字符数据。

 

编码转换:怎样将GB2312 编码的字符串转换为ISO-8859-1 编码的字符串?【基础】

String s1 = "你好";

String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

 

是否可以继承String ? 【基础】

String 类是final 类,故不可以继承。

 

有疑问,欢迎在下方留言喔

 

 

 

 

 

你可能感兴趣的:(javase)