繁体   English   中英

如果尝试使用反射将值设置为String类的value []字段,则Java 6和Java 7会产生不同的结果

[英]Java 6 and Java 7 yield different results, if an attempt is made to set a value to the value[] field of the String class using reflection

以下代码尝试使用Java 7将值设置为String类的private final char value[]字段。

package test;

import java.lang.reflect.Field;

public final class Test 
{
    static
    {
        try
        {
            Field value = String.class.getDeclaredField("value");
            value.setAccessible(true);
            value.set("Hello World", value.get("1234567890"));
        }
        catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e)
        {
            System.out.println(e.toString());
        }
    }

    public static void main(String[] args) 
    {
        System.out.println("Hello World");
    }
}

并在控制台上静默显示1234567890 ,对此毫无疑问。


当我尝试使用Java 6进行以下操作时,

package test;

import java.lang.reflect.Field;

public final class Test
{
    static
    {
        try
        {
            Field value = String.class.getDeclaredField("value");
            value.setAccessible(true);
            value.set("Hello World", value.get("1234567890"));
        }
        catch (IllegalArgumentException e)
        {
            System.out.println(e.toString());
        }
        catch (IllegalAccessException e)
        {
            System.out.println(e.toString());
        }
        catch (NoSuchFieldException e)
        {
            System.out.println(e.toString());
        }
        catch (SecurityException e)
        {
            System.out.println(e.toString());
        }
    }
    public static void main(String[] args)
    {
        System.out.println("Hello World");
    }
}

它导致引发以下异常。

线程“主”中的异常java.lang.ArrayIndexOutOfBoundsException

当此语句中value.get("1234567890")的长度value.set("Hello World", value.get("1234567890"));起作用时,此方法value.set("Hello World", value.get("1234567890")); 大于或等于String Hello World

例如,

如果以下语句(如前面的代码片段所示)

value.set("Hello World", value.get("1234567890"));

替换为以下内容

value.set("Hello World", value.get("12345678901"));

那么,当set()方法的第二个参数的长度小于第一个参数的长度时,为什么这在Java 6中不起作用(或者可能更低,我没有尝试)?

顺便说一句,我可以理解,根本不建议以这种方式处理具有反射的私有字段,这是最糟糕的。

那么,当set()方法的第二个参数的长度小于第一个参数的长度时,为什么这在Java 6中不起作用(或者可能更低,我没有尝试)?

在Java 6中,您正在设法将value字符数组设置为新的引用-但是您没有更改其他指定字符串所引用的char[]部分的其他字段。

我不记得确切的字段名称,但这是这样的:

char[] value;
int offset;
int count;

因此,对于“覆盖”整个字符数组的字符串, offset将为0, count将为value.length 现在,如果您用较短的 char[]替换value ,但不更改count ,则offset + count超出了数组的末尾……它超出了数组的范围。 这样做是为了使诸如substring操作不需要复制字符数据,它们只是创建一个新对象,该对象引用具有不同偏移量/计数值的现有数组。

从更新版本5开始的Java 7中,字符串没有此偏移量/计数概念。 相反,每个字符串都有其自己的字符数组,并且开始和结束是隐式的。 我怀疑这就是为什么它在Java 7中对您有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM