一个简单的Java代码,运行良好,但其运行方式有点难以理解

一个简单的Java代码,运行良好,但其运行方式有点难以理解,java,Java,下面的简单Java程序通过语句System.out.println(“Hello-World”)显示字符串Hello-World但它没有。它只是用另一个字符串替换它,在本例中,Good Day并将其显示在控制台上。字符串Hello World根本不显示。让我们看一下以下Java中的简单代码片段 package goodday; import java.lang.reflect.Field; final public class Main { public static void m

下面的简单Java程序通过语句
System.out.println(“Hello-World”)显示字符串Hello-World但它没有。它只是用另一个字符串替换它,在本例中,Good Day并将其显示在控制台上。字符串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);
        }
    }
}


这里只有一个关于这个代码的问题。它的工作原理与预期完全一致,但我无法缩短字符串的长度祝您愉快。如果尝试这样做,将导致
java.lang.ArrayIndexOutOfBoudsException
。若长度增加,则程序运行良好,但显示字符串中的其余字符被截断,这意味着两个字符串的长度应该大致相同。为什么?这是我无法理解的。

字段是一个
char[]
字段,它在内部存储字符串用作其后台存储的字符数组。其他字段指示字符数组的初始偏移量以及字符串的长度。(因此,要获取子字符串,它只需创建一个新的
字符串
对象,该对象引用相同的
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));
    }
}

当然你知道你永远不应该在真实的代码中这样做吗?我了解Java很长时间了,但以前从未见过这样的smth,非常好的问题:你应该知道不应该鼓励这样做…:-)