[英]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.