add method

This commit is contained in:
Looly 2022-09-21 21:48:06 +08:00
parent f62a36b045
commit 400a7b7e04
2 changed files with 80 additions and 0 deletions

View File

@ -1,7 +1,9 @@
package cn.hutool.core.reflect; package cn.hutool.core.reflect;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -213,6 +215,57 @@ public class ModifierUtil {
public static boolean isInterface(final Class<?> clazz) { public static boolean isInterface(final Class<?> clazz) {
return null != clazz && clazz.isInterface(); return null != clazz && clazz.isInterface();
} }
/**
* 设置final的field字段可以被修改
* 只要不会被编译器内联优化的 final 属性就可以通过反射有效的进行修改 -- 修改后代码中可使用到新的值;
* <p>以下属性编译器会内联优化无法通过反射修改</p>
* <ul>
* <li> 基本类型 byte, char, short, int, long, float, double, boolean</li>
* <li> Literal String 类型(直接双引号字符串)</li>
* </ul>
* <p>以下属性可以通过反射修改</p>
* <ul>
* <li>基本类型的包装类 ByteCharacterShortLongFloatDoubleBoolean</li>
* <li>字符串通过 new String("")实例化</li>
* <li>自定义java类</li>
* </ul>
* <pre class="code">
* {@code
* //示例移除final修饰符
* class JdbcDialects {private static final List<Number> dialects = new ArrayList<>();}
* Field field = ReflectUtil.getField(JdbcDialects.class, fieldName);
* ReflectUtil.removeFinalModify(field);
* ReflectUtil.setFieldValue(JdbcDialects.class, fieldName, dialects);
* }
* </pre>
*
* @param field 被修改的field不可以为空
* @throws UtilException IllegalAccessException等异常包装
* @author dazer
* @since 5.8.8
*/
public static void removeFinalModify(final Field field) {
if (null == field || false == hasModifier(field, ModifierUtil.ModifierType.FINAL)) {
return;
}
//将字段的访问权限设为true即去除private修饰符的影响
if (false == field.isAccessible()) {
field.setAccessible(true);
}
try {
//去除final修饰符的影响将字段设为可修改的
final Field modifiersField = Field.class.getDeclaredField("modifiers");
//Field modifiers 是私有的
modifiersField.setAccessible(true);
//& 位与运算符按位与 运算规则两个数都转为二进制然后从高位开始比较如果两个数都为1则为1否则为0
//~ 位非运算符按位取反运算规则转成二进制如果位为0结果是1如果位为1结果是0.
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (final NoSuchFieldException | IllegalAccessException e) {
//内部工具类基本不抛出异常
throw new UtilException(e, "IllegalAccess for {}.{}", field.getDeclaringClass(), field.getName());
}
}
//-------------------------------------------------------------------------------------------------------- Private method start //-------------------------------------------------------------------------------------------------------- Private method start
/** /**

View File

@ -1,10 +1,14 @@
package cn.hutool.core.util; package cn.hutool.core.util;
import cn.hutool.core.reflect.FieldUtil;
import cn.hutool.core.reflect.ModifierUtil; import cn.hutool.core.reflect.ModifierUtil;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class ModifierUtilTest { public class ModifierUtilTest {
@ -20,4 +24,27 @@ public class ModifierUtilTest {
private static void ddd() { private static void ddd() {
} }
@Test
public void setFinalFieldValueTest() {
final String fieldName = "DIALECTS";
final List<Number> dialects =
Arrays.asList(
1,
2,
3,
99
);
final Field field = FieldUtil.getField(JdbcDialects.class, fieldName);
ModifierUtil.removeFinalModify(field);
FieldUtil.setFieldValue(JdbcDialects.class, fieldName, dialects);
Assert.assertEquals(dialects, FieldUtil.getFieldValue(JdbcDialects.class, fieldName));
}
@SuppressWarnings("unused")
public static class JdbcDialects {
private static final List<Number> DIALECTS =
Arrays.asList(1L, 2L, 3L);
}
} }