字符串String被设计成immutable(不可改变)的,String的value值也是final类型,如何改变值呢?
package com.hanshimeng.other;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
String str1 = "hello world";
String str2 = "hello world";
String str3 = str1.substring(6);
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
System.out.println("----------------");
Field field = String.class.getDeclaredField("value");
field.setAccessible(true); // 设置访问权限不检查
char[] value = (char[])field.get(str1);
value[6] = '1';
value[7] = '2';
value[8] = '3';
value[9] = '4';
value[10] = '5';
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
}
}
输出结果:
hello world
hello world
world
----------------
hello 12345
hello 12345
world
修改str1的值str2也会改变,说明他们引用的是同一个对象;那为何str3没有改变呢,咱先来看一下substring的方法实现:
// 该版本是JDK7,至于7之前的版本可能有不一样的情况
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
以上代码解释:
当beginIndex不为0时,返回的是new的String对象;当beginIndex为0时,返回的是原对象本身;
我们都知道new对象后是在堆中创建的,是一个新的对象,与str1和str2的值没有关系。
再看以下的代码就更有意思了:
System.out.println("hello world" == str1);
System.out.println("hello world".equals(str1));
System.out.println("hello world".toString());
System.out.println("hello 12345" == str1);
System.out.println("hello 12345".equals(str1));
输出结果:
true
true
hello 12345
false
true
String 的变量值是存放在 JVM 的常量池中的,同时指向 “hello world” 的引用的 s即 String 对象,
存放在堆区,我们通过反射区修改的值并不是常量池中的 “hello world” ,而是 堆区中的对象 s 的值,
所以我们输出 s的时候就是hello 12345,那么为什么初始值比较修改后的值的时候会出现 true 呢?
我们看看 System.out.println(“hello world”.toString()); 这行代码,输出结果是 hello 12345,这是因为
“hello world”.toString() 的时候,会去常量池中去找 "hello world"的引用,它的引用就是 s ,所以输出的
是 s 的值,即 “hello 12345”,所以,到这里,我们就知道了,为什么 str1 == “hello world” 和 str1.equals(“hello world”) 返回 true 了
如需转载,请注明作者出处
作者:hanshimeng
出处:https://blog.csdn.net/hanshimeng