From fae97d0d3e408fd65303f745b73ce939d30b488b Mon Sep 17 00:00:00 2001
From: duandazhi
Date: Wed, 21 Sep 2022 14:03:14 +0800
Subject: [PATCH 1/6] =?UTF-8?q?ReflectUtil=E6=96=B0=E5=A2=9EsetFieldModify?=
=?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E8=AE=BE=E7=BD=AE=EF=BC=9Afinal?=
=?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=8F=AF=E4=BB=A5=E8=A2=AB=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/hutool/core/util/ReflectUtil.java | 31 +++++++++++++++++++
1 file changed, 31 insertions(+)
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 5a81bb816..5b6392faf 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,6 +9,7 @@ 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;
@@ -345,7 +346,10 @@ public class ReflectUtil {
value = ClassUtil.getDefaultValue(fieldType);
}
+ // 设置private私有(私有方法、属性、类)可以被外部方式
setAccessible(field);
+ // 设置final字段可以被修改
+ setFieldModify(field);
try {
field.set(obj instanceof Class ? null : obj, value);
} catch (IllegalAccessException e) {
@@ -1108,6 +1112,33 @@ public class ReflectUtil {
return accessibleObject;
}
+
+ /**
+ * 设置final的field字段可以被修改
+ * @param field 被修改的field,不可以为空
+ * @throws UtilException IllegalAccessException等异常包装
+ * @since 5.8.8
+ * @author dazer
+ */
+ public static void setFieldModify(Field field) {
+ 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);
+ modifiersField.setInt(field, field.getModifiers() &~ Modifier.FINAL);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ //内部,工具类,基本不抛出异常
+ throw new UtilException(e, "IllegalAccess for {}.{}", field.getDeclaringClass(), field.getName());
+ }
+ }
+ }
+
/**
* 获取方法的唯一键,结构为:
*
From bcfbd28c129f6ce89d713ab57d635dc7c6f06663 Mon Sep 17 00:00:00 2001
From: duandazhi
Date: Wed, 21 Sep 2022 14:04:01 +0800
Subject: [PATCH 2/6] =?UTF-8?q?ReflectUtilTest=E5=A2=9E=E5=8A=A0=EF=BC=9A?=
=?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=96=B9=E6=B3=95=EF=BC=8C=E9=AA=8C=E8=AF=81?=
=?UTF-8?q?=E5=AF=B9=20final=E5=B1=9E=E6=80=A7=E7=9A=84=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/hutool/core/util/JdbcDialects.java | 9 +++++++++
.../cn/hutool/core/util/ReflectUtilTest.java | 16 ++++++++++++++++
2 files changed, 25 insertions(+)
create mode 100644 hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java b/hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java
new file mode 100644
index 000000000..ead033e44
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java
@@ -0,0 +1,9 @@
+package cn.hutool.core.util;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class JdbcDialects {
+ private static final List DIALECTS =
+ Arrays.asList(1L, 2L, 3L);
+}
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 7792804a8..efae77797 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
@@ -13,7 +13,9 @@ import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
/**
@@ -268,4 +270,18 @@ public class ReflectUtilTest {
int[] intArray = ReflectUtil.newInstanceIfPossible(int[].class);
Assert.assertArrayEquals(new int[0], intArray);
}
+
+ @Test
+ public void setFieldValueTest() {
+ String fieldName = "DIALECTS";
+ final List dialects =
+ Arrays.asList(
+ 1,
+ 2,
+ 3,
+ 99
+ );
+ ReflectUtil.setFieldValue(JdbcDialects.class, fieldName, dialects);
+ Assert.assertEquals(dialects, ReflectUtil.getFieldValue(JdbcDialects.class, fieldName));
+ }
}
From c9fe27124452741e58e1e13f9bebd3968abc8a5e Mon Sep 17 00:00:00 2001
From: duandazhi
Date: Wed, 21 Sep 2022 14:29:14 +0800
Subject: [PATCH 3/6] =?UTF-8?q?setFieldModify=E5=A2=9E=E5=8A=A0=E9=9D=9E?=
=?UTF-8?q?=E7=A9=BA=E6=A0=A1=E9=AA=8C=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=BD=8D?=
=?UTF-8?q?=E4=B8=8E=E3=80=81=E4=BD=8D=E9=9D=9E=20=E8=BF=90=E7=AE=97?=
=?UTF-8?q?=E7=AC=A6=E8=AF=B4=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/hutool/core/util/ReflectUtil.java | 33 ++++++++++---------
1 file changed, 18 insertions(+), 15 deletions(-)
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 5b6392faf..af975a036 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
@@ -1112,7 +1112,6 @@ public class ReflectUtil {
return accessibleObject;
}
-
/**
* 设置final的field字段可以被修改
* @param field 被修改的field,不可以为空
@@ -1121,20 +1120,24 @@ public class ReflectUtil {
* @author dazer
*/
public static void setFieldModify(Field field) {
- 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);
- modifiersField.setInt(field, field.getModifiers() &~ Modifier.FINAL);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- //内部,工具类,基本不抛出异常
- throw new UtilException(e, "IllegalAccess for {}.{}", field.getDeclaringClass(), field.getName());
+ 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());
+ }
}
}
}
From a8b89e48e35f25cfa24a5afa6b4636aa84b7a6d5 Mon Sep 17 00:00:00 2001
From: duandazhi
Date: Wed, 21 Sep 2022 14:37:48 +0800
Subject: [PATCH 4/6] =?UTF-8?q?JdbcDialects=E6=94=B9=E6=88=90=E5=86=85?=
=?UTF-8?q?=E9=83=A8=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/test/java/cn/hutool/core/util/JdbcDialects.java | 9 ---------
.../test/java/cn/hutool/core/util/ReflectUtilTest.java | 5 +++++
2 files changed, 5 insertions(+), 9 deletions(-)
delete mode 100644 hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java b/hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java
deleted file mode 100644
index ead033e44..000000000
--- a/hutool-core/src/test/java/cn/hutool/core/util/JdbcDialects.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package cn.hutool.core.util;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class JdbcDialects {
- private static final List DIALECTS =
- Arrays.asList(1L, 2L, 3L);
-}
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 efae77797..5a36189ae 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
@@ -271,6 +271,11 @@ public class ReflectUtilTest {
Assert.assertArrayEquals(new int[0], intArray);
}
+ public static class JdbcDialects {
+ private static final List DIALECTS =
+ Arrays.asList(1L, 2L, 3L);
+ }
+
@Test
public void setFieldValueTest() {
String fieldName = "DIALECTS";
From f19d94dc8d47b1319ac401d8afdc2f12322b3a5f Mon Sep 17 00:00:00 2001
From: duandazhi
Date: Wed, 21 Sep 2022 14:51:27 +0800
Subject: [PATCH 5/6] =?UTF-8?q?setFieldModify=E5=A2=9E=E5=8A=A0=E8=AF=A6?=
=?UTF-8?q?=E7=BB=86=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/hutool/core/util/ReflectUtil.java | 15 +++++++++++++++
1 file changed, 15 insertions(+)
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 af975a036..33fd6ebbf 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
@@ -1114,6 +1114,21 @@ public class ReflectUtil {
/**
* 设置final的field字段可以被修改
+ *
+ * 只要不会被编译器内联优化的 final 属性就可以通过反射有效的进行修改 -- 修改后代码中可使用到新的值;
+ *
+ *
以下属性,编译器会内联优化,无法通过反射修改:
+ *
+ * - 基本类型 byte, char, short, int, long, float, double, boolean
+ * - Literal String 类型(直接双引号字符串)
+ *
+ * 以下属性,可以通过反射修改:
+ *
+ * - 基本类型的包装类 Byte、Character、Short、Long、Float、Double、Boolean
+ * - 字符串,通过 new String("")实例化
+ * - 自定义java类
+ *
+ *
* @param field 被修改的field,不可以为空
* @throws UtilException IllegalAccessException等异常包装
* @since 5.8.8
From 724728987d5630658cf6f5d82f96af05192647ee Mon Sep 17 00:00:00 2001
From: duandazhi
Date: Wed, 21 Sep 2022 16:45:10 +0800
Subject: [PATCH 6/6] =?UTF-8?q?1=E3=80=81=E9=87=8D=E5=91=BD=E5=90=8D?=
=?UTF-8?q?=EF=BC=9AsetFieldModify-->removeFinalModify=202=E3=80=81?=
=?UTF-8?q?=E7=A7=BB=E9=99=A4=EF=BC=9A=20ReflectUtil.setFieldValue?=
=?UTF-8?q?=E8=87=AA=E5=8A=A8=E8=BF=9B=E8=A1=8C=EF=BC=9AremoveFinalModify?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/cn/hutool/core/util/ReflectUtil.java | 16 +++++++++++-----
.../cn/hutool/core/util/ReflectUtilTest.java | 3 +++
2 files changed, 14 insertions(+), 5 deletions(-)
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 33fd6ebbf..d56e01966 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
@@ -304,6 +304,7 @@ public class ReflectUtil {
* 设置字段值
* 若值类型与字段类型不一致,则会尝试通过 {@link Convert} 进行转换
* 若字段类型是原始类型而传入的值是 null,则会将字段设置为对应原始类型的默认值(见 {@link ClassUtil#getDefaultValue(Class)})
+ * 如果是final字段,setFieldValue,调用这可以先调用 {@link ReflectUtil#removeFinalModify(Field)}方法去除final修饰符
*
* @param obj 对象,static字段则此处传Class
* @param fieldName 字段名
@@ -322,7 +323,8 @@ public class ReflectUtil {
/**
* 设置字段值
* 若值类型与字段类型不一致,则会尝试通过 {@link Convert} 进行转换
- * 若字段类型是原始类型而传入的值是 null,则会将字段设置为对应原始类型的默认值(见 {@link ClassUtil#getDefaultValue(Class)})
+ * 若字段类型是原始类型而传入的值是 null,则会将字段设置为对应原始类型的默认值(见 {@link ClassUtil#getDefaultValue(Class)})
+ * 如果是final字段,setFieldValue,调用这可以先调用 {@link ReflectUtil#removeFinalModify(Field)}方法去除final修饰符
*
* @param obj 对象,如果是static字段,此参数为null
* @param field 字段
@@ -346,10 +348,7 @@ public class ReflectUtil {
value = ClassUtil.getDefaultValue(fieldType);
}
- // 设置private私有(私有方法、属性、类)可以被外部方式
setAccessible(field);
- // 设置final字段可以被修改
- setFieldModify(field);
try {
field.set(obj instanceof Class ? null : obj, value);
} catch (IllegalAccessException e) {
@@ -1129,12 +1128,19 @@ public class ReflectUtil {
* 自定义java类
*
*
+ *
+ * //示例,移除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 setFieldModify(Field field) {
+ public static void removeFinalModify(Field field) {
if (field != null) {
if (ModifierUtil.hasModifier(field, ModifierUtil.ModifierType.FINAL)) {
//将字段的访问权限设为true:即去除private修饰符的影响
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 5a36189ae..6170ec61b 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
@@ -286,7 +286,10 @@ public class ReflectUtilTest {
3,
99
);
+ Field field = ReflectUtil.getField(JdbcDialects.class, fieldName);
+ ReflectUtil.removeFinalModify(field);
ReflectUtil.setFieldValue(JdbcDialects.class, fieldName, dialects);
+
Assert.assertEquals(dialects, ReflectUtil.getFieldValue(JdbcDialects.class, fieldName));
}
}