黑马程序员技术交流社区
标题:
使用反射修改String的问题
[打印本页]
作者:
房建斌
时间:
2014-3-10 16:43
标题:
使用反射修改String的问题
本帖最后由 房建斌 于 2014-3-11 11:35 编辑
利用反射修改String,修改之前,用substring方法截取了一个字符串,但是修改了原字符串后,截取的字符串的值也修改了。按理来说,substring返回的是一个新字符串,在字符串常量池中和原字符串不是共享的。照这个结果来看,substring方法还是和原字符串共享了一部分,并不是创建一个新的字符串了。请高手解答
//jdk版本1.6.0_11
String s1 = "Hello World";
String s2 = "Hello World";
String s3 = s1.substring(6);
System.out.println(s1); // Hello World
System.out.println(s2); // Hello World
System.out.println(s3); // World
//得到String的value字段
Field field = s1.getClass().getDeclaredField("value");
//设置可访问
field.setAccessible(true);
//得到char数组的值
char[] value = (char[])field.get(s1);
//更改数组的值
value[6] = 'H';
value[7] = 'e';
value[8] = 'i';
value[9] = 'm';
value[10] = 'a';
System.out.println(s1); // Hello Heima
System.out.println(s2); // Hello Heima
System.out.println(s3); //在修改之前加上s3 = s3.intern()结果为World,不加上结果为Heima。
复制代码
作者:
陈果
时间:
2014-3-11 11:11
我认为通过substring方法截取到的子串,然后赋给一个新的字符串变量,这时并没有在内存中开辟空间来单独存储,而是指向索引处,这样不仅获取了数据,而且节约了内存,不知道这样考虑对不对。
作者:
chen_x
时间:
2014-3-11 11:36
如果String s3=s1.subString(6)只是将s3取值指向了内存中已有的常量字符串"Hello World"的某个索引处,
按这样理解的话,再创建一个String s4=s1.substring(6), 那s4和s3应该指向"Hello World"的同一索引处,s3==s4应该为ture吧?
但实际上
public class Test6{
public static void main(String[] args){
String s1 = "Hello World";
String s2 = "Hello World";
String s3 = s1.substring(6);
String s4 = s1.substring(6);
System.out.println(s1==s2);
System.out.println(s3==s4);
}
}
运行结果为true
false
说明s1和s2是相等的,但是s3和s4是不等的,这个怎么解释?
---可能没必要深究的这么细,不过还是希望了解substring内情的给解答下~~~
作者:
syusikoku
时间:
2014-3-11 11:38
<P>希望下面的例子能帮你解开疑惑。你是少了field.set(rtp2, newValue);
你需要使用Field对象把修改后的值给设置到对应的对象身上去。
rtp2 就是你要设置的对象,而newValue就是你要设置的新的值 </P>
<P>/**
* 测试要求: 我们使用反射获取ReflectTestPoint字节码文件中的字段,把值里面的bbs更换成wwwweb
* @param args
*/
public static void main(String[] args) throws Exception {
ReflectTestPoint rtp2 = new ReflectTestPoint();
// 我们先获取字节码文件中的所有的对象
// 因为我们的bean中是私有的字段所以我们使用DeclaredFields来进行获取
// Field[] rtps=ReflectTestPoint.class.getDeclaredFields();
Field[] rtps = rtp2.getClass().getDeclaredFields();
// 遍历数组
for (Field field : rtps) {
// 因为里面有私有的方法所以我们需要开启暴力反射
field.setAccessible(true); // 开启暴力反射
// 获取字段的值
// 如何判断字段的类型了
// 如果字段是字符串的类型
if (field.getType() == String.class) {
// 获取里面的值
// String oldValue=(String) field.get(new ReflectTestPoint());
String oldValue = (String) field.get(rtp2);
System.out.println("字段:" + field.getName() + "原始值:" + oldValue);
/**
* 字段都获取出来了 字段:itcastBBs原始值:bbs.itcast.com
* 字段:itheimaBBs原始值:bbs.itheima.com
* 字段:itcastWeb原始值:www.itcast.com
* 字段:itheimaWeb原始值:www.itheima.com
*/
// String newValue = oldValue.replace('b', 'w');
String newValue=oldValue.replace("bbs", "www");
// 将修改后的值设置给对象
field.set(rtp2, newValue); // 使用字段对象把修改后的值设置给对象ReflectTestPoint中的字段
System.out.println("更新后的数据:"+rtp2);
/**
* 字段:itcastBBs原始值:bbs.itcast.com
更新后的数据:wws.itcast.com:::==bbs.itheima.com:::==www.itcast.com:::==www.itheima.com
字段:itheimaBBs原始值:bbs.itheima.com
更新后的数据:wws.itcast.com:::==wws.itheima.com:::==www.itcast.com:::==www.itheima.com
字段:itcastWeb原始值:www.itcast.com
更新后的数据:wws.itcast.com:::==wws.itheima.com:::==www.itcast.com:::==www.itheima.com
字段:itheimaWeb原始值:www.itheima.com
更新后的数据:wws.itcast.com:::==wws.itheima.com:::==www.itcast.com:::==www.itheima.com
*/
//怎么实现替换字符串了?
/**
* 字段:itcastBBs原始值:bbs.itcast.com
更新后的数据:www.itcast.com:::==bbs.itheima.com:::==www.itcast.com:::==www.itheima.com
字段:itheimaBBs原始值:bbs.itheima.com
更新后的数据:www.itcast.com:::==www.itheima.com:::==www.itcast.com:::==www.itheima.com
字段:itcastWeb原始值:www.itcast.com
更新后的数据:www.itcast.com:::==www.itheima.com:::==www.itcast.com:::==www.itheima.com
字段:itheimaWeb原始值:www.itheima.com
更新后的数据:www.itcast.com:::==www.itheima.com:::==www.itcast.com:::==www.itheima.com
*/
}
}
}</P>
复制代码
作者:
房建斌
时间:
2014-3-11 12:02
刚查看了一下Substring源码,substring会以当前字符串的字符数组为标准,返回一个新的字符串。所以多次substring的值是不相等的,虽然内容是一样的。由于substring是用了原来的数组字符串char[] value.所以当更改了原字符串的值的话,substring的内容也会随之更改。我是这么理解的。不知这么理解对不对,期待有大神的解答
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2