Java中的String为什么是不可变的? -- String源码分析(二)

2014-11-24 03:16:54 · 作者: · 浏览: 4
上的字符变为下划线“_”。 至少在我们自己写的普通代码中不能够做到,因为我们根本不能够访问到这个value引用,更不能通过这个引用去修改数组。 那么用什么方式可以访问私有成员呢? 没错,用反射, 可以反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。下面是实例代码:
	public static void testReflection() throws Exception {
		
		//创建字符串"Hello World", 并赋给引用s
		String s = "Hello World"; 
		
		System.out.println("s = " + s);	//Hello World
		
		//获取String类中的value字段
		Field valueFieldOfString = String.class.getDeclaredField("value");
		
		//改变value属性的访问权限
		valueFieldOfString.setAccessible(true);
		
		//获取s对象上的value属性的值
		char[] value = (char[]) valueFieldOfString.get(s);
		
		//改变value所引用的数组中的第5个字符
		value[5] = '_';
		
		System.out.println("s = " + s);  //Hello_World
	}

打印结果为: s = Hello World
s = Hello_World

在这个过程中,s始终引用的同一个String对象,但是再反射前后,这个String对象发生了变化, 也就是说,通过反射是可以修改所谓的“不可变”对象的。但是一般我们不这么做。这个反射的实例还可以说明一个问题:如果一个对象,他组合的其他对象的状态是可以改变的,那么这个对象很可能不是不可变对象。例如一个Car对象,它组合了一个Wheel对象,虽然这个Wheel对象声明成了private final 的,但是这个Wheel对象内部的状态可以改变, 那么就不能很好的保证Car对象不可变。