diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c0aead78..61b139015 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,13 @@ ------------------------------------------------------------------------------------------------------------- -# 5.8.8.M1 (2022-09-20) +# 5.8.8.M1 (2022-09-21) ### 🐣新特性 * 【core 】 StreamUtil.of方法新增对 Iterator 支持;StreamUtil.of(Iterable) 方法优化(pr#807@Gitee) * 【core 】 增加.wgt格式的MimeType(pr#2617@Github) * 【core 】 EnumUtil.getBy增加带默认值重载(issue#I5RZU6@Gitee) +* 【core 】 ModifierUtil和ReflectUtil增加removeFinalModify(pr#810@Gitee) ### 🐞Bug修复 * 【core 】 修复FileNameUtil.cleanInvalid无法去除换行符问题(issue#I5RMZV@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ModifierUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ModifierUtil.java index dec42bed0..224950a94 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ModifierUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ModifierUtil.java @@ -1,5 +1,7 @@ package cn.hutool.core.util; +import cn.hutool.core.exceptions.UtilException; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -262,6 +264,58 @@ public class ModifierUtil { public static boolean isAbstract(Method method) { return hasModifier(method, ModifierType.ABSTRACT); } + + /** + * 设置final的field字段可以被修改 + *
+ * 只要不会被编译器内联优化的 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