![](/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.