diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java index 9560e564e..694489028 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/ModifierUtil.java @@ -1,7 +1,9 @@ package cn.hutool.core.reflect; +import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.util.ArrayUtil; +import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Modifier; @@ -213,6 +215,57 @@ public class ModifierUtil { public static boolean isInterface(final Class> clazz) { return null != clazz && clazz.isInterface(); } + + /** + * 设置final的field字段可以被修改 + * 只要不会被编译器内联优化的 final 属性就可以通过反射有效的进行修改 -- 修改后代码中可使用到新的值; + *
以下属性,编译器会内联优化,无法通过反射修改:
+ *以下属性,可以通过反射修改:
+ *
+ * {@code
+ * //示例,移除final修饰符
+ * class JdbcDialects {private static final List dialects = new ArrayList<>();}
+ * Field field = ReflectUtil.getField(JdbcDialects.class, fieldName);
+ * ReflectUtil.removeFinalModify(field);
+ * ReflectUtil.setFieldValue(JdbcDialects.class, fieldName, dialects);
+ * }
+ *
+ *
+ * @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
/**
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ModifierUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ModifierUtilTest.java
index fae64188a..a7385ce13 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/ModifierUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/ModifierUtilTest.java
@@ -1,10 +1,14 @@
package cn.hutool.core.util;
+import cn.hutool.core.reflect.FieldUtil;
import cn.hutool.core.reflect.ModifierUtil;
import org.junit.Assert;
import org.junit.Test;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
public class ModifierUtilTest {
@@ -20,4 +24,27 @@ public class ModifierUtilTest {
private static void ddd() {
}
+
+ @Test
+ public void setFinalFieldValueTest() {
+ final String fieldName = "DIALECTS";
+ final List