From eef7943d8a6f0688acff8eb705b3bcb8e7fbaab6 Mon Sep 17 00:00:00 2001
From: Looly
+ * 只要不会被编译器内联优化的 final 属性就可以通过反射有效的进行修改 -- 修改后代码中可使用到新的值;
+ *
+ * 以下属性,编译器会内联优化,无法通过反射修改:
+ *
+ *
+ * 以下属性,可以通过反射修改:
+ *
+ *
+ *
+ * //示例,移除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等异常包装
+ * @since 5.8.8
+ * @author dazer
+ */
+ public static void removeFinalModify(Field field) {
+ if (field != null) {
+ if (hasModifier(field, ModifierUtil.ModifierType.FINAL)) {
+ //将字段的访问权限设为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/main/java/cn/hutool/core/util/ReflectUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
index d56e01966..f61027b0a 100755
--- a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
@@ -9,7 +9,6 @@ import cn.hutool.core.exceptions.InvocationTargetRuntimeException;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Filter;
-import java.lang.reflect.Modifier;
import cn.hutool.core.lang.reflect.MethodHandleUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.map.WeakConcurrentMap;
@@ -1141,26 +1140,7 @@ public class ReflectUtil {
* @author dazer
*/
public static void removeFinalModify(Field field) {
- if (field != null) {
- if (ModifierUtil.hasModifier(field, ModifierUtil.ModifierType.FINAL)) {
- //将字段的访问权限设为true:即去除private修饰符的影响
- if (!field.isAccessible()) {
- field.setAccessible(true);
- }
- try {
- //去除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 (NoSuchFieldException | IllegalAccessException e) {
- //内部,工具类,基本不抛出异常
- throw new UtilException(e, "IllegalAccess for {}.{}", field.getDeclaringClass(), field.getName());
- }
- }
- }
+ ModifierUtil.removeFinalModify(field);
}
/**
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ReflectUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ReflectUtilTest.java
index 6170ec61b..3b82a70a6 100755
--- a/hutool-core/src/test/java/cn/hutool/core/util/ReflectUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/ReflectUtilTest.java
@@ -74,7 +74,7 @@ public class ReflectUtilTest {
@Test
public void getFieldTest() {
// 能够获取到父类字段
- Field privateField = ReflectUtil.getField(TestSubClass.class, "privateField");
+ final Field privateField = ReflectUtil.getField(TestSubClass.class, "privateField");
Assert.assertNotNull(privateField);
}
@@ -87,14 +87,14 @@ public class ReflectUtilTest {
@Test
public void setFieldTest() {
- TestClass testClass = new TestClass();
+ final TestClass testClass = new TestClass();
ReflectUtil.setFieldValue(testClass, "a", "111");
Assert.assertEquals(111, testClass.getA());
}
@Test
public void invokeTest() {
- TestClass testClass = new TestClass();
+ final TestClass testClass = new TestClass();
ReflectUtil.invoke(testClass, "setA", 10);
Assert.assertEquals(10, testClass.getA());
}
@@ -155,7 +155,7 @@ public class ReflectUtilTest {
private String n;
}
- public static Method getMethodWithReturnTypeCheck(Class> clazz, boolean ignoreCase, String methodName, Class>... paramTypes) throws SecurityException {
+ public static Method getMethodWithReturnTypeCheck(final Class> clazz, final boolean ignoreCase, final String methodName, final Class>... paramTypes) throws SecurityException {
if (null == clazz || StrUtil.isBlank(methodName)) {
return null;
}
@@ -163,7 +163,7 @@ public class ReflectUtilTest {
Method res = null;
final Method[] methods = ReflectUtil.getMethods(clazz);
if (ArrayUtil.isNotEmpty(methods)) {
- for (Method method : methods) {
+ for (final Method method : methods) {
if (StrUtil.equals(methodName, method.getName(), ignoreCase)
&& ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)
&& (res == null
@@ -252,22 +252,22 @@ public class ReflectUtilTest {
@Test
public void newInstanceIfPossibleTest(){
//noinspection ConstantConditions
- int intValue = ReflectUtil.newInstanceIfPossible(int.class);
+ final int intValue = ReflectUtil.newInstanceIfPossible(int.class);
Assert.assertEquals(0, intValue);
- Integer integer = ReflectUtil.newInstanceIfPossible(Integer.class);
+ final Integer integer = ReflectUtil.newInstanceIfPossible(Integer.class);
Assert.assertEquals(new Integer(0), integer);
- Map, ?> map = ReflectUtil.newInstanceIfPossible(Map.class);
+ final Map, ?> map = ReflectUtil.newInstanceIfPossible(Map.class);
Assert.assertNotNull(map);
- Collection> collection = ReflectUtil.newInstanceIfPossible(Collection.class);
+ final Collection> collection = ReflectUtil.newInstanceIfPossible(Collection.class);
Assert.assertNotNull(collection);
- Week week = ReflectUtil.newInstanceIfPossible(Week.class);
+ final Week week = ReflectUtil.newInstanceIfPossible(Week.class);
Assert.assertEquals(Week.SUNDAY, week);
- int[] intArray = ReflectUtil.newInstanceIfPossible(int[].class);
+ final int[] intArray = ReflectUtil.newInstanceIfPossible(int[].class);
Assert.assertArrayEquals(new int[0], intArray);
}
@@ -277,8 +277,8 @@ public class ReflectUtilTest {
}
@Test
- public void setFieldValueTest() {
- String fieldName = "DIALECTS";
+ public void setFieldValueWithFinalTest() {
+ final String fieldName = "DIALECTS";
final List