字符串为引用数据类型,是线性表的一种。

面试中最常问的String类为何不可变?我们先来看String类的源代码:

Java修改stringBuilder 的值 java string不能修改_java

 我们可以看到string类是由 char value[]数组实现的;很多人误以为String类不可变是由于此数组被final修饰,下面我们研究一下final关键词:

1:修饰属性

final int a=10;//则a无法修改,只能为10

2:修饰引用数据类型

final int[] arr=new int[3];//则其值不能修(引用保存的地址)
arr只能指向这个数组,但地址中包含的内容可以修改

3:修饰方法

该方法不可被重写,(不可被子类覆盖)

4:修饰类

该类不可有子类(不可以被继承)

·String类被final修饰,其不可以被继承,保证了JDK使用的String类是相同的版本,使用方法一致;

·String类内部的数组value[](引用数据类型)被final修饰,导致其指向不可变,但内容是可变的,以上两个fianl都不是导致String不可变的原因

·而其不可变的真正原因是因为private修饰了数组value[],导致外部类不可访问,而String类也没有提供修改的方法,故String类不可变,String类提供的所有修改串的方法,都会产生新串(即产生新地址),而不会改变串。

为什么String类设置为不可改变?

字符串常量池:

字符串常量池可以节省大量的内存空间。如果String类可变就不可能有字符串常量池

线程安全:

不可变的对象天生就是线程安全的,这样可以避免在多线程环境下对String做同步操作

hashcode:

Java修改stringBuilder 的值 java string不能修改_面试_02

String类在被创建的时,hashcode就被缓存到hash成员变量中,因为String类是不可变的,所以hashcode是不会改变的。这样每次想使用hashcode不用重新计算直接用,提高了效率


关于常量池:

String str1="picupqi";//第一次出现,放入常量池
String str2="picupqi";//常量池已经有相同的串,str2直接使用
String str3=new String("picupqi");//一旦出现new就开辟了新地址

此时str1==str2(true)        str1==str3(false)-------'=='比较的是否同一对象‘equals'比较是否内容相等

Java修改stringBuilder 的值 java string不能修改_ide_03

如果想修改字符串,我们可以使用StringBuliderl类(异步处理,线程不安全,效率高)或者StringBuffer类(同步处理,线程安全,效率低)

//String-->StringBulider对象
//1
String str="picupqi";
StringBulider sb1=new StringBulider(str);
//2
StringBulider sb2=new StringBulider();
sb2.append()str;

//StringBulider-->String
String ret=sb2.toString();