這是一個比較特殊的知識點,需要從HotSpot與Dalvik的區別說起。
問題起因
相信大家在繼承RecycleView時,對ViewHolder中的itemView都有重寫的慾望。這個itemView是final類型的,不容許被修改,極大的限制了開發的自由。
那首先想到的就是利用反射來修改該字段。可是運行會報錯。
創建一個通用方法進行反射修改屬性值,如下:
public static void modify(Object object, String fieldName, Object newFieldValue) throws Exception {
Field field = object.getClass().getDeclaredField(fieldName);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true); //Field 的 modifiers 是私有的
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
if(!field.isAccessible()) {
field.setAccessible(true);
}
field.set(object, newFieldValue);
}
在實際運行時,會報錯,提示說沒有modifiers字段。這也就表明,Android編譯後的dex字節碼中,並沒有java那一套複雜屬性訪問控制邏輯。
反射時忽視final修飾符
調整代碼,不管final,直接嘗試修改itemView
Field field = RecyclerView.ViewHolder.class.getField("itemView");
field.set(viewHolder, someNewItemView);
此時是可以正常運行的。