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)); } }