java 反射 修改静态变量_JAVA 反射修改static,final修饰的变量

调用对应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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值