![](/img/trans.png)
[英]UnsupportedEncodingException thrown when using Resin and Grails
[英]UnsupportedEncodingException is not getting thrown, if we change final property value using reflection
package com.java.random.practice;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class App
{
private static final String ENCODING = "\\UTF-8";
public static void main( String[] args ) throws UnsupportedEncodingException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
{
URLEncoder.encode("anyValue", ENCODING);
}
}
上面的代码在使用“\”进行编码时会抛出异常UnsupportedEncodingException,但是当我们使用反射来修改值时,它不会显示任何异常,请参见下面的代码:
package com.java.random.practice;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLEncoder;
public class App
{
private static final String ENCODING = "UTF-8";
public static void main( String[] args ) throws UnsupportedEncodingException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
{
App app=new App();
Field field = app.getClass().getDeclaredField("ENCODING");
field.setAccessible(true);
Field modifiersField =
Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true); modifiersField.setInt(field,
field.getModifiers() & ~Modifier.FINAL); field.set(null, "\\UTF-8");
String s= URLEncoder.encode("anyValue", ENCODING);
System.out.println(s);
}
}
为什么会有这种奇怪的行为?
编译时间常数的值由编译器内联。
这是什么意思?
假设有private static final String STR = "Foo";
. 在这里,我们确定(使用标准语言规则,不包括反射,因为它是一种破坏语言强制执行的所有保证的工具,例如:防止访问private
成员、修改final
等) STR
的值应该始终为"Foo"
并且信息在编译时也是已知的。
这允许编译器优化像System.out.println(STR);
这样的代码。 并消除了查找STR
值的需要,而是直接使用它,这将产生与我们编写System.out.println("Foo");
(因为编译器知道值并且“理论上”总是相同的)。
因此,即使我们使用反射并将新值重新分配给STR
,它也不会影响代表System.out.println("Foo");
因为它不再依赖于STR
。
在你的情况下
String s= URLEncoder.encode("anyValue", ENCODING);
将像您将其编写为一样进行编译
String s= URLEncoder.encode("anyValue", "UTF-8");
(因为private static final String ENCODING = "UTF-8";
ENCODINT
的值为"UTF-8"
,并且在使用ENCODINT
的地方内联)。 因此,即使您为ENCODINT
(此处为“\UTF-8”)分配新值,它也不会影响表示URLEncoder.encode("anyValue", "UTF-8")
字节码,因为它不使用/参考ENCODING
.
如果要防止内联,请不要使ENCODING
成为编译时间常数。 换句话说,确保分配的值需要在运行时“计算”。 例如,您可以使用private static final String ENCODING = "UTF-8".substring(0);
.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.