3

我找到了下面的代码片段:

import java.lang.reflect.Field;
public class Test {
    public static void main(String[] args) {
        System.out.println("Inside main");
    }
    static {
        try {
            Field value = String.class.getDeclaredField("value");
            value.setAccessible(true);
            value.set("Inside main", value.get("Inside static bolck"));
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

根据我的理解,输出应该是Inside static bolck,但输出是Inside stat相同的字符长度Inside main
*如果我增加 Inside main 的长度,输出长度也会增加。
有人可以解释一下吗?我对反射没有太多的了解。

4

4 回答 4

4

在我的 JDK 上,String还有一个count成员,需要更新以反映新的长度。

还有一个offset字段,可能需要也可能不需要更新(可能不是这种情况)。

最后,有一个hash字段,在您更改后将不再正确value

由于此代码依赖于特定实现的未记录细节String,因此它非常脆弱且高度不可移植。例如(帽子提示@assylias),Oracle 已经删除了JDK 7u6 中的countandoffset字段。如果您要从 7u5 升级到 7u6,那么您的代码会突然出现不同的行为。

于 2013-03-15T12:49:19.810 回答
1

代码对 String 类的实际实现做出假设,例如,该类有一个名为“value”的字段。

由于 String 类的内部状态不是 API 或语言规范的一部分,因此不同供应商的 VM 甚至同一供应商的不同 VM 版本之间的实际实现会有所不同。

于 2013-03-15T12:59:30.993 回答
0

"Inside main" 在 value[] 中包含 11 个字符(value[] 是 String 类中的私有字段)
Stringvalue[]在您定义 String 的第一个位置被初始化"Inside main"。现在您正在value[]使用反射更改字符串中的私有实例变量的值,然后它必须仅适合字符串中的 11 个字符Inside static bolck

于 2013-03-15T13:03:06.200 回答
0

当您更改“Inside main”时,您可以value.get()将字符串 <=“Inside main”。将 -“Inside main”更改为“Inside main (8 个空格)”并打印

"Inside static bolck"
于 2013-03-15T13:13:53.980 回答