diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/ReflectUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/ReflectUtil.java
index 06985a355..d1f19fdbd 100644
--- a/hutool-core/src/main/java/cn/hutool/core/reflect/ReflectUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/reflect/ReflectUtil.java
@@ -33,7 +33,8 @@ public class ReflectUtil {
*
* @param executable 可执行的反射对象
* @return 描述符
- * @apiNote 参考:jvm定义的Field Descriptors(字段描述)
+ * @link jvm定义的Field Descriptors(字段描述)
+ * @link 关于类型描述符的博客
*
例:
*
* - {@code ReflectUtil.getDescriptor(Object.class.getMethod("hashCode")) // "()I"}
@@ -41,20 +42,19 @@ public class ReflectUtil {
* - {@code ReflectUtil.getDescriptor(Object.class.getMethod("equals", Object.class)) // "(Ljava/lang/Object;)Z"}
* - {@code ReflectUtil.getDescriptor(ReflectUtil.class.getDeclaredMethod("appendDescriptor", Class.clas, StringBuilder.class)) // "(Ljava/lang/Class;Ljava/lang/StringBuilder;)V"}
* - {@code ReflectUtil.getDescriptor(ArrayUtil.class.getMethod("isEmpty", Object[].class)) // "([Ljava/lang/Object;)Z"}
- *
Object.class.getMethod("hashCode")
+ *
+ * @author VampireAchao
*/
public static String getDescriptor(Executable executable) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append('(');
Class>[] parameters = executable.getParameterTypes();
for (Class> parameter : parameters) {
- appendDescriptor(parameter, stringBuilder);
+ stringBuilder.append(getDescriptor(parameter));
}
if (executable instanceof Method) {
Method method = (Method) executable;
- stringBuilder.append(')');
- appendDescriptor(method.getReturnType(), stringBuilder);
- return stringBuilder.toString();
+ return stringBuilder.append(')').append(getDescriptor(method.getReturnType())).toString();
} else if (executable instanceof Constructor) {
return stringBuilder.append(")V").toString();
}
@@ -62,65 +62,63 @@ public class ReflectUtil {
}
/**
- * 拼接描述符
+ * 获取类型描述符,这是编译成class文件后的二进制名称
*
- * @param clazz 类
- * @param stringBuilder 描述符
+ * @param clazz 类
* @link jvm定义的Field Descriptors(字段描述)
+ * @link 关于类型描述符的博客
+ * 例:
+ *
+ * - {@code ReflectUtil.getDescriptor(boolean.class) "Z"}
+ * - {@code ReflectUtil.getDescriptor(Boolean.class) "Ljava/lang/Boolean;"}
+ * - {@code ReflectUtil.getDescriptor(double[][][].class) "[[[D"}
+ * - {@code ReflectUtil.getDescriptor(int.class) "I"}
+ * - {@code ReflectUtil.getDescriptor(Integer.class) "Ljava/lang/Integer;"}
+ *
+ * @author VampireAchao
*/
- private static void appendDescriptor(Class> clazz, StringBuilder stringBuilder) {
+ public static String getDescriptor(Class> clazz) {
+ StringBuilder stringBuilder = new StringBuilder();
Class> currentClass;
for (currentClass = clazz;
currentClass.isArray();
currentClass = currentClass.getComponentType()) {
+ // 如果当前是数组描述符
stringBuilder.append('[');
}
if (currentClass.isPrimitive()) {
- stringBuilder.append(getDescriptorChar(currentClass));
+ // 只有下面九种基础数据类型以及数组,才有独立的描述符
+ final char descriptor;
+ // see sun.invoke.util.Wrapper
+ // These must be in the order defined for widening primitive conversions in JLS 5.1.2
+ if (currentClass == boolean.class) {
+ descriptor = 'Z';
+ } else if (currentClass == byte.class) {
+ descriptor = 'B';
+ } else if (currentClass == short.class) {
+ descriptor = 'S';
+ } else if (currentClass == char.class) {
+ descriptor = 'C';
+ } else if (currentClass == int.class) {
+ descriptor = 'I';
+ } else if (currentClass == long.class) {
+ descriptor = 'J';
+ } else if (currentClass == float.class) {
+ descriptor = 'F';
+ } else if (currentClass == double.class) {
+ descriptor = 'D';
+ } else if (currentClass == void.class) {
+ // VOID must be the last type, since it is "assignable" from any other type:
+ descriptor = 'V';
+ } else {
+ throw new AssertionError();
+ }
+ stringBuilder.append(descriptor);
} else {
+ // 否则一律是 "L"+类名.replace('.', '/')+";"格式的对象类型
stringBuilder.append('L').append(currentClass.getName().replace('.', '/')).append(';');
}
-
- }
-
- /**
- * 获取单个描述符
- *
- * @param currentClass 当前类
- * @return 描述符
- */
- private static char getDescriptorChar(Class> currentClass) {
- if ( currentClass == boolean.class) {
- return 'Z';
- }
- if ( currentClass == byte.class) {
- return 'B';
- }
- if (currentClass == short.class) {
- return 'S';
- }
- if (currentClass == char.class) {
- return 'C';
- }
- if (currentClass == int.class) {
- return 'I';
- }
- if (currentClass == long.class) {
- return 'J';
- }
- if (currentClass == float.class) {
- return 'F';
- }
- if (currentClass == double.class) {
- return 'D';
- }
- if (currentClass == Object.class) {
- return 'L';
- }
- if (currentClass == void.class) {
- return 'V';
- }
- throw new AssertionError();
+ return stringBuilder.toString();
}
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/reflect/ReflectUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/reflect/ReflectUtilTest.java
index a89659531..60d2bdbb8 100644
--- a/hutool-core/src/test/java/cn/hutool/core/reflect/ReflectUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/reflect/ReflectUtilTest.java
@@ -1,11 +1,13 @@
package cn.hutool.core.reflect;
import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.ArrayUtil;
import lombok.Data;
import lombok.SneakyThrows;
import org.junit.Test;
+import java.util.Arrays;
+import java.util.Collection;
+
/**
* 反射工具类单元测试
*
@@ -113,10 +115,21 @@ public class ReflectUtilTest {
@Test
@SneakyThrows
public void testGetDescriptor() {
+ // methods
Assert.equals("()I", ReflectUtil.getDescriptor(Object.class.getMethod("hashCode")));
Assert.equals("()Ljava/lang/String;", ReflectUtil.getDescriptor(Object.class.getMethod("toString")));
Assert.equals("(Ljava/lang/Object;)Z", ReflectUtil.getDescriptor(Object.class.getMethod("equals", Object.class)));
- Assert.equals("(Ljava/lang/Class;Ljava/lang/StringBuilder;)V", ReflectUtil.getDescriptor(ReflectUtil.class.getDeclaredMethod("appendDescriptor", Class.class, StringBuilder.class)));
- Assert.equals("([Ljava/lang/Object;)Z", ReflectUtil.getDescriptor(ArrayUtil.class.getMethod("isEmpty", Object[].class)));
+ Assert.equals("(II)I", ReflectUtil.getDescriptor(Integer.class.getDeclaredMethod("compare", int.class, int.class)));
+ Assert.equals("([Ljava/lang/Object;)Ljava/util/List;", ReflectUtil.getDescriptor(Arrays.class.getMethod("asList", Object[].class)));
+ Assert.equals("()V", ReflectUtil.getDescriptor(Object.class.getConstructor()));
+ // clazz
+ Assert.equals("Z", ReflectUtil.getDescriptor(boolean.class));
+ Assert.equals("Ljava/lang/Boolean;", ReflectUtil.getDescriptor(Boolean.class));
+ Assert.equals("[[[D", ReflectUtil.getDescriptor(double[][][].class));
+ Assert.equals("I", ReflectUtil.getDescriptor(int.class));
+ Assert.equals("Ljava/lang/Integer;", ReflectUtil.getDescriptor(Integer.class));
+ Assert.equals("V", ReflectUtil.getDescriptor(void.class));
+ Assert.equals("Ljava/lang/Void;", ReflectUtil.getDescriptor(Void.class));
+ Assert.equals("Ljava/lang/Object;", ReflectUtil.getDescriptor(Object.class));
}
}