mac*_*rog 84 java string reflection string-pool
Java字符串池加上反射可以在Java中产生一些难以想象的结果:
import java.lang.reflect.Field;
class MessingWithString {
public static void main (String[] args) {
String str = "Mario";
toLuigi(str);
System.out.println(str + " " + "Mario");
}
public static void toLuigi(String original) {
try {
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(original, "Luigi".toCharArray());
} catch (Exception ex) {
// Ignore exceptions
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将打印:
"Luigi Luigi"
Run Code Online (Sandbox Code Playgroud)
马里奥怎么了?
Jon*_*eet 96
马里奥怎么了?
你基本上改变了它.是的,通过反射你可以违反字符串的不变性......并且由于字符串实习,这意味着任何使用"Mario"(除了在更大的字符串常量表达式中,这将在编译时解析)将结束在程序的其余部分中作为"Luigi".
这种事情是为什么反射需要安全权限...
需要注意的是表达str + " " + "Mario"并没有执行任何编译时的串联,由于左结合+.这是有效的(str + " ") + "Mario",这就是你仍然看到的原因Luigi Luigi.如果您将代码更改为:
System.out.println(str + (" " + "Mario"));
Run Code Online (Sandbox Code Playgroud)
...然后你会看到Luigi Mario编译器将实际" Mario"插入到不同的字符串中"Mario".
Ama*_*dan 24
它被设定为Luigi.Java中的字符串是不可变的; 因此,编译器可以将所有提及解释"Mario"为对同一个String常量池项的引用(粗略地说,"内存位置").您使用反射来更改该项目; 所以"Mario"你的代码中的所有内容现在都像你写的一样"Luigi".
字符串文字存储在字符串池中,并使用它们的规范值.两个"Mario"文字不仅仅是具有相同值的字符串,它们是同一个对象.操纵其中一个(使用反射)将修改它们的"两者",因为它们只是对同一对象的两个引用.
你只是改变了String的字符串常量池 Mario到Luigi这是由多个引用StringS,所以每一个引用的文字 Mario是现在Luigi.
Field stringValue = String.class.getDeclaredField("value");
Run Code Online (Sandbox Code Playgroud)
您已从类中获取了char[]命名value字段String
stringValue.setAccessible(true);
Run Code Online (Sandbox Code Playgroud)
让它可访问.
stringValue.set(original, "Luigi".toCharArray());
Run Code Online (Sandbox Code Playgroud)
你改变了original String 字段Luigi.但原来Mario的String 文字和文字所属的String游泳池和所有被拘留.这意味着具有相同内容的所有文字都指向相同的内存地址.
String a = "Mario";//Created in String pool
String b = "Mario";//Refers to the same Mario of String pool
a == b//TRUE
//You changed 'a' to Luigi and 'b' don't know that
//'a' has been internally changed and
//'b' still refers to the same address.
Run Code Online (Sandbox Code Playgroud)
基本上你已经更改了所有引用字段中反映的String池的Mario .如果你创建(即)而不是文字,你将不会面对这种行为,因为你将有两个不同的s.String Objectnew String("Mario")Mario