- 調用對應Class的getDeclaredField或getField方法,獲取要修改的Filed;
2個方法的差別在於:
getDeclaredField可獲取當前Class內所有變量名(private,protect,public,friend),但不會獲取父類變量;
getField可獲取當前Class及父Class內所有訪問級別為public的變量名; - final修飾的常量不可修改,判斷field對應數據為常量則直接返回false;
常量的判斷條件:
1)使用了final修飾
2)數據類型為基本類型或者String類型
原因:
使用final修飾后,被引用的數據地址將不可改變,我們只能嘗試修改地址上的內容,而常量不能修改地址內容,或者說修改不生效。 - 如果訪問級別不是public,調用setAccessible(true)獲得訪問權限;
- 如果使用了final修飾,而沒有使用static修飾,可以調用setAccessible(true)獲得修改權限,或者修改Modifier,去除final修飾符;
如果同時使用了static和final,則只能通過修改Modifier去除final修飾符來獲取修改權限; - 判斷要修改的數據類型,如果為基本類型,調用對應的基本類型修改方法,其他情況直接調用set方法;
- 對修改過的部分還原。
綜合上述步驟,對應代碼如下:
public static boolean setValue(@Nullable Object source, @NonNull Class<?> target,
@NonNull String name, @Nullable Object value) {
Field field = null;
int modify = 0;
Field modifiersField = null;
boolean removeFinal = false;
try {
field = target.getDeclaredField(name);
modify = field.getModifiers();
//final修飾的基本類型不可修改
if (field.getType().isPrimitive() && Modifier.isFinal(modify)) {
return false;
}
//獲取訪問權限
if (!Modifier.isPublic(modify) || Modifier.isFinal(modify)) {
field.setAccessible(true);
}
//static final同時修飾
removeFinal = Modifier.isStatic(modify) && Modifier.isFinal(modify);
if (removeFinal) {
modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, modify & ~Modifier.FINAL);
}
//按照類型調用設置方法
if (value != null && field.getType().isPrimitive()) {
if ("int".equals(field.getType().getName()) && value instanceof Number) {
field.setInt(source, ((Number) value).intValue());
} else if ("boolean".equals(field.getType().getName()) && value instanceof Boolean) {
field.setBoolean(source, (Boolean) value);
} else if ("byte".equals(field.getType().getName()) && value instanceof Byte) {
field.setByte(source, (Byte) value);
} else if ("char".equals(field.getType().getName()) && value instanceof Character) {
field.setChar(source, (Character) value);
} else if ("double".equals(field.getType().getName()) && value instanceof Number) {
field.setDouble(source, ((Number) value).doubleValue());
} else if ("long".equals(field.getType().getName()) && value instanceof Number) {
field.setLong(source, ((Number) value).longValue());
} else if ("float".equals(field.getType().getName()) && value instanceof Number) {
field.setFloat(source, ((Number) value).floatValue());
} else if ("short".equals(field.getType().getName()) && value instanceof Number) {
field.setShort(source, ((Number) value).shortValue());
} else {
return false;
}
} else {
field.set(source, value);
}
} catch (Exception e) {
return false;
} finally {
try {
//權限還原
if (field != null) {
if (removeFinal && modifiersField != null) {
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
modifiersField.setAccessible(false);
}
if (!Modifier.isPublic(modify) || Modifier.isFinal(modify)) {
field.setAccessible(false);
}
}
} catch (IllegalAccessException e) {
//
}
}
return true;
}
2020-06-18