黑马程序员技术交流社区
标题:
用反射改变字符串,为什么有的可变,有的不可变
[打印本页]
作者:
奚华
时间:
2012-11-18 10:39
标题:
用反射改变字符串,为什么有的可变,有的不可变
大家看下面的两段代码,微小的差别,但结果截然相反,跪求真相,跪求解释!!!!!
1、使用反射改变传入change方法的对象的final String str成员,我们在声明str时就给str赋值为"ABC":str没被改变仍为"ABC"
import java.lang.reflect.Field;
public class ReflectTest {
private final String str="ABC";//声明时赋值
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ReflectTest rt=new ReflectTest();
System.out.println("---打印改变前的str字符串的值---");
System.out.println(rt.str);//打印出来ABC
rt.change(rt);
System.out.println("---打印改变后的str字符串的值---");
System.out.println(rt.str);//打印出来是ABC
}
/**
* 试图改变obj对象里的的字符串成员
* @param obj
* @throws Exception
*/
public void change(Object obj) throws Exception
{
Field[] fild=obj.getClass().getDeclaredFields();
for(Field f:fild)
{
if(!f.isAccessible())//设置权限
f.setAccessible(true);
if(f.getType()==String.class)
{
String str=new String("CBA");//想把这些字符串设置为"CBA"
f.set(obj, str);
}
}
}
}
复制代码
2、
使用反射改变传入change方法的对象的final String str成员,我们在声明str时并没有给str赋值,接着我使用一个初始化块给str赋值为"ABC",大家擦亮眼睛看结果:str被改变了被变为了"CBA"
import java.lang.reflect.Field;
public class ReflectTest {
private final String str;//声明时不赋值,在下面的初始化块中赋值!
//给str赋值为"ABC"
{
str="ABC";
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ReflectTest rt=new ReflectTest();
System.out.println("---打印改变前的str字符串的值---");
System.out.println(rt.str);//打印出来ABC
rt.change(rt);
System.out.println("---打印改变后的str字符串的值---");
System.out.println(rt.str);//打印出来是CBA
}
/**
* 试图改变obj对象里的的字符串成员
* @param obj
* @throws Exception
*/
public void change(Object obj) throws Exception
{
Field[] fild=obj.getClass().getDeclaredFields();
for(Field f:fild)
{
if(!f.isAccessible())//设置权限
f.setAccessible(true);
if(f.getType()==String.class)
{
String str=new String("CBA");//想把这些字符串设置为"CBA"
f.set(obj, str);
}
}
}
}
复制代码
求解释,求真像!
作者:
李刚
时间:
2012-11-21 23:00
private final String str="ABC";//声明时赋值
这里创建的是对象吧,“ABC”在堆内存中。所以不能改变。
private final String str;//声明时不赋值,在下面的初始化块中赋值!
//给str赋值为"ABC"
{
str="ABC";
}
这里的,“ABC”在栈内存中吧,没有创建对象。
String str=new String("CBA");//想把这些字符串设置为"CBA"
f.set(obj, str);
这里重新创建了对象,其实就是两个str同时指向了new String("CBA");
个人观点
作者:
李刚
时间:
2012-11-23 18:50
public class ReflectTest3 {
private final String str="ABC";
/*
* public ReflectTest3(String str){ this.str=str; }
*/
public String getStr() {
return str;
}
/**
*
* @param args
*
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ReflectTest3 rt = new ReflectTest3();
System.out.println("---打印改变前的str字符串的值---");
System.out.println(rt.str);// 打印出来ABC
System.out.println(rt.str.hashCode());
rt.change(rt.str);
System.out.println("---打印改变后的str字符串的值---");
System.out.println(rt.str);// 打印出来还是ABC,没有被改变
System.out.println(rt.str.hashCode());
}
/**
*
* 试图改变obj对象里的的字符串成员
*
* @param obj
*
* @throws Exception
*/
public void change(String str) throws Exception
{
Class cls = str.getClass();// 获得str的Class对象
Field fil = cls.getDeclaredField("value");// 获得String类中的char数组value[]的Filed变量
fil.setAccessible(true);// 由于value变量是一个private的所以设置权限
char[] ch = { 'D', 'S', 'W', 'Q' };
fil.set(str, ch);// 改变value所指向的数组,使value指向ch数组
}
}
这个输出结果可以改变private final String str="ABC";的值,final好像只是能够使对象的hashCode值不变。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2