java通过映射修改String的值

字符串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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值