以下简单的Java程序似乎通过语句显示字符串Hello World,System.out.println("Hello World");但它没有.它只是用另一个字符串替换它,在这种情况下,美好的一天!并在控制台上显示它.字符串Hello World根本不显示.我们来看看Java中的以下简单代码片段.
package goodday;
import java.lang.reflect.Field;
final public class Main
{
public static void main(String[] args)
{
System.out.println("Hello World");
}
static
{
try
{
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set("Hello World", value.get("Good Day !!"));
}
catch (Exception e)
{
throw new AssertionError(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里只有一个关于此代码的问题.它完全按预期工作,但我无法减少字符串的好日子!.如果尝试这样做,则会导致a java.lang.ArrayIndexOutOfBoudsException.如果长度增加,程序运行良好但显示字符串中的其余字符被截断意味着两个字符串的长度应该有些相同.为什么?这是我无法理解的事情.
该value字段是一个char[]内部存储字符串用作其后备存储的字符数组的字段.其他字段表示字符数组的初始偏移量和字符串的长度.(因此,为了获取子字符串,它只是创建一个新String对象,该对象引用相同char[]但具有不同的起始偏移和长度.)
如果你也修改这些字段,你可以用字符串做任何你喜欢的事情.样品:
import java.lang.reflect.Field;
public class Test
{
// Obviously in real code you wouldn't use Exception like this...
// Although hacking string values with reflection is worse, of course.
public static void main(String[] args) throws Exception
{
System.out.println("Hello World");
replaceHelloWorld("Goodbye!");
System.out.println("Hello World");
replaceHelloWorld("Hello again!");
System.out.println("Hello World");
}
static void replaceHelloWorld(String text) throws Exception
{
// Note: would probably want to do hash as well...
copyField(text, "Hello World", "value");
copyField(text, "Hello World", "offset");
copyField(text, "Hello World", "count");
}
static void copyField(String source, String target, String name)
throws Exception
{
Field field = String.class.getDeclaredField(name);
field.setAccessible(true);
field.set(target, field.get(source));
}
}
Run Code Online (Sandbox Code Playgroud)