如果尝试使用反射将值设置为String类的value[]字段,Java6和Java7会产生不同的结果
下面的代码尝试使用Java 7将值设置为String类的如果尝试使用反射将值设置为String类的value[]字段,Java6和Java7会产生不同的结果,java,string,reflection,java-7,java-6,Java,String,Reflection,Java 7,Java 6,下面的代码尝试使用Java 7将值设置为String类的私有最终字符值[]字段 package test; import java.lang.reflect.Field; public final class Test { static { try { Field value = String.class.getDeclaredField("value"); value.setAccessibl
私有最终字符值[]
字段
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");
}
}
它导致引发以下异常
线程“main”java.lang.ArrayIndexOutOfBoundsException中出现异常
当语句value.set(“Hello World”,value.get(“1234567890”))中value.get(“1234567890”)的长度为
大于或等于字符串Hello World
比如说,
如果出现以下语句(如前面的代码段所示)
替换为以下内容
value.set("Hello World", value.get("12345678901"));
那么,当set()
方法的第二个参数的长度小于第一个参数时,为什么不使用Java6(或者可能更低,我没有尝试过)呢
顺便说一句,我可以理解以这种方式处理带有反射的私有字段是不推荐的,而且是最糟糕的
那么,当set()方法的第二个参数的长度小于第一个参数时,为什么Java 6(或者可能更低,我没有尝试过)不能实现这一点呢
在Java 6中,您正设法将值
字符数组设置为新引用,但您没有更改其他字段,这些字段指定字符串引用的char[]
部分
我记不起确切的字段名,但它是这样的:
char[] value;
int offset;
int count;
因此,对于“覆盖”整个字符数组的字符串,offset
将为0,count
将为value.length
。现在,如果用较短的字符[]
替换值
,但不更改计数
,则偏移量+计数
超出了数组的末尾。。。它在数组的边界之外。这样做的目的是,像substring
这样的操作不需要复制字符数据-它们只创建一个引用现有数组的新对象,具有不同的偏移/计数值
在Java7中,从更新5开始,字符串没有这个偏移量/计数概念;相反,每个字符串都有自己的字符数组,并且起始和结束都是隐式的。我想这就是为什么它在Java7中适用的原因
char[] value;
int offset;
int count;