Java中String类型为什么不可变?

1.源码中String类不可变的原因

String类的源码

public final class String{
   //用字符数组来存数值
   private final char value[];
 
}

虽然String是final类型的类,且value也是final类型的数组,但这不是String不可变的根本原因,String不可变是因为value是private,且并没有提供对外的get和set

final关键字修饰作用

修饰类:表明该类不可被继承,类中的所有成员方法都隐式的被指定为final方法

修饰方法:不可被重写,JVM会尝试将其内联,以提高运行效率

修饰变量:不可被改变,修饰引用变量表示引用不可变,引用指向的内容可变

修饰常量:在编译阶段会存入常量池中

2.如何改变String类的内容

String的值是不能被改变的,可能有人看到下面这个会觉得String的内容有被改变。但是实际上在内存中没改变的不是String 的值而是改变了引用的对象。然后将指针指向新的String 对象。所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响。如果要改变字符串的内容,可以用StringBuffer与StringBuilder.

1.第一种

public static void main(String[] args) {

String s = "hey";
s=s+" how are you";
System.out.println(s);

}


//输出的值为   “hey how are you”

2.第二种对于引用类型,会在堆中创建实例,然后对象的具体指只在栈中进行保存。堆种保存的值栈种保存的值栈种对应的引用地址。

String中的value是引用类型,所以可以做到在不改变堆中引用的情况下,改变栈中具体的值即可

代码示例

public class StringModifyTest {
	public static void main(String[] args) throws Exception{
		// 1.  mock一个String
		String str = "Melodfy";
		// 2. 通过反射过去对象
			// 反射获取对象的三种方法
			// 1. Class.forName("类全限定名")
			// 2. 类名.class()
			// 3. 实例.getClass()
		Class<? extends String> strCls = str.getClass();
		// 3. 通过反射获取指定参数,得到一个属性对象
		Field field = strCls.getDeclaredField("value");
		// 私有属性要设置可访问,否则访问操作时异常
		filed.setAccessible(true); 
		// 4. 根据属性对象获取参数的具体指
		char[] result = (char[])field.get(str);
		// 5. 验证输出结果
		Systemg,out.println("变更前结果:");
		for(char c : result) {
			System.out.print(c);
		}

		// 6. 操作变更,然后输出验证
		System.out.println("变更后结果:");
		char[2] = 'w';
		for(char c : result) {
			System.out.print(c);
		}
		
	}
}

3.不可变的好处和坏处

1)线程安全性(好处)

在并发场景下,多个线程读取同一个资源,是不会引发竞态条件的。只有在对资源进行些操作时才有危险。不可变对象不能被修改,所以是线程安全的。

2)节省空间,提高效率(好处)

String还有字符串常量池的属性,on和two两个变量指向的是同一个地址。在大量使用字符串的情况下,可以节省内存空间,提高效率。

String的不可变条件是必要条件,要是内存中字符串内容能够改来改去,这么做就完全没有意义。

3)修改性能不高(坏处)

由于String 的不可变性,每次对String 类型进行改变的时候,都会生成一个新的String 对象,然后将指针指向新的String对象。

4.总结:

1.保存字符串的数组被final修饰且为私有的,并且String类没有提供/暴露修改这个字符串的方法

2.String类被final修饰导致其不能被继承,进而避免了子类破坏String 不可变

猜你喜欢

转载自blog.csdn.net/weixin_58419099/article/details/131035928