diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java index 521586022..b76049317 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java @@ -18,9 +18,9 @@ import org.dromara.hutool.core.exception.HutoolException; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.Opt; import org.dromara.hutool.core.map.WeakConcurrentMap; +import org.dromara.hutool.core.reflect.ClassDescUtil; import org.dromara.hutool.core.reflect.MethodUtil; import org.dromara.hutool.core.reflect.ModifierUtil; -import org.dromara.hutool.core.reflect.ReflectUtil; import java.io.Serializable; import java.lang.invoke.SerializedLambda; @@ -98,7 +98,7 @@ public class LambdaUtil { final Class implClass = ClassLoaderUtil.loadClass(serializedLambda.getImplClass(), true); if ("".equals(methodName)) { for (final Constructor constructor : implClass.getDeclaredConstructors()) { - if (ReflectUtil.getDescriptor(constructor).equals(serializedLambda.getImplMethodSignature())) { + if (ClassDescUtil.getDesc(constructor, false).equals(serializedLambda.getImplMethodSignature())) { return new LambdaInfo(constructor, serializedLambda); } } @@ -106,7 +106,7 @@ public class LambdaUtil { final Method[] methods = MethodUtil.getMethods(implClass); for (final Method method : methods) { if (method.getName().equals(methodName) - && ReflectUtil.getDescriptor(method).equals(serializedLambda.getImplMethodSignature())) { + && ClassDescUtil.getDesc(method, false).equals(serializedLambda.getImplMethodSignature())) { return new LambdaInfo(method, serializedLambda); } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ClassDescUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ClassDescUtil.java index 83ad81744..fd3da1cce 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ClassDescUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ClassDescUtil.java @@ -167,14 +167,21 @@ public class ClassDescUtil { } /** - * 获取类描述 + * 获取类描述,这是编译成class文件后的二进制名称 *
{@code
-	 * boolean[].class => "[Z"
-	 * Object.class => "Ljava/lang/Object;"
+	 *    getDesc(boolean.class)       // Z
+	 *    getDesc(Boolean.class)       // Ljava/lang/Boolean;
+	 *    getDesc(double[][][].class)  // [[[D
+	 *    getDesc(int.class)           // I
+	 *    getDesc(Integer.class)       // Ljava/lang/Integer;
 	 * }
* * @param c class. * @return desc. + * + * @author VampireAchao + * @see jvm定义的Field Descriptors(字段描述) + * @see 关于类型描述符的博客 */ public static String getDesc(Class c) { final StringBuilder ret = new StringBuilder(); @@ -199,22 +206,35 @@ public class ClassDescUtil { /** * 获取方法或构造描述
- * 方法: + * 方法(appendName为{@code true}): *
{@code
-	 * int do(int arg1) => "do(I)I"
-	 * void do(String arg1,boolean arg2) => "do(Ljava/lang/String;Z)V"
+	 *    int do(int arg1) => "do(I)I"
+	 *    void do(String arg1,boolean arg2) => "do(Ljava/lang/String;Z)V"
 	 * }
* 构造: - *
-	 * "()V", "(Ljava/lang/String;I)V"
-	 * 
+ *
{@code
+	 *    "()V", "(Ljava/lang/String;I)V"
+	 * }
+ * + *

当appendName为{@code false}时:

+ *
{@code
+	 *    getDesc(Object.class.getMethod("hashCode"))                    // ()I
+	 *    getDesc(Object.class.getMethod("toString"))                    // ()Ljava/lang/String;
+	 *    getDesc(Object.class.getMethod("equals", Object.class))        // (Ljava/lang/Object;)Z
+	 *    getDesc(ArrayUtil.class.getMethod("isEmpty", Object[].class))  // "([Ljava/lang/Object;)Z"
+	 * }
* * @param methodOrConstructor 方法或构造 + * @param appendName 是否包含方法名称 * @return 描述 + * + * @author VampireAchao + * @see jvm定义的Field Descriptors(字段描述) + * @see 关于类型描述符的博客 */ - public static String getDesc(final Executable methodOrConstructor) { + public static String getDesc(final Executable methodOrConstructor, final boolean appendName) { final StringBuilder ret = new StringBuilder(); - if (methodOrConstructor instanceof Method) { + if (appendName && methodOrConstructor instanceof Method) { ret.append(methodOrConstructor.getName()); } ret.append('('); diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ReflectUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ReflectUtil.java index 018d899e8..7c05ba362 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ReflectUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ReflectUtil.java @@ -71,99 +71,4 @@ public class ReflectUtil { } return accessibleObject; } - - /** - * 获取jvm定义的Field Descriptors(字段描述) - *

例:

- * - * - * @param executable 可执行的反射对象 - * @return 描述符 - * @author VampireAchao - * @see jvm定义的Field Descriptors(字段描述) - * @see 关于类型描述符的博客 - */ - public static String getDescriptor(final Executable executable) { - final StringBuilder stringBuilder = new StringBuilder(32); - stringBuilder.append('('); - final Class[] parameters = executable.getParameterTypes(); - for (final Class parameter : parameters) { - stringBuilder.append(getDescriptor(parameter)); - } - if (executable instanceof Method) { - final Method method = (Method) executable; - return stringBuilder.append(')').append(getDescriptor(method.getReturnType())).toString(); - } else if (executable instanceof Constructor) { - return stringBuilder.append(")V").toString(); - } - throw new IllegalArgumentException("Unknown Executable: " + executable); - } - - /** - * 获取类型描述符,这是编译成class文件后的二进制名称 - *

例:

- * - * - * @param clazz 类 - * @return 描述字符串 - * @author VampireAchao - * @see jvm定义的Field Descriptors(字段描述) - * @see 关于类型描述符的博客 - */ - public static String getDescriptor(final Class clazz) { - final StringBuilder stringBuilder = new StringBuilder(32); - Class currentClass; - for (currentClass = clazz; - currentClass.isArray(); - currentClass = currentClass.getComponentType()) { - // 如果当前是数组描述符 - stringBuilder.append('['); - } - if (currentClass.isPrimitive()) { - // 只有下面九种基础数据类型以及数组,才有独立的描述符 - 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(';'); - } - return stringBuilder.toString(); - } - } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/kotlin/KClassUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/kotlin/KClassUtil.java index 5ef7479f0..8ee6087bf 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/kotlin/KClassUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/kotlin/KClassUtil.java @@ -113,7 +113,7 @@ public class KClassUtil { final Object[] parameterValues = getParameterValues(constructor, valueProvider); try { return (T) KCallable.call(constructor, parameterValues); - } catch (RuntimeException e) { + } catch (final RuntimeException e) { exception = e; } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/spi/SPIException.java b/hutool-core/src/main/java/org/dromara/hutool/core/spi/SPIException.java index 9188bd46e..aff5a20ca 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/spi/SPIException.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/spi/SPIException.java @@ -12,38 +12,74 @@ package org.dromara.hutool.core.spi; -import org.dromara.hutool.core.exception.ExceptionUtil; -import org.dromara.hutool.core.text.StrUtil; +import org.dromara.hutool.core.exception.HutoolException; /** * SPI异常 * * @author looly */ -public class SPIException extends RuntimeException { +public class SPIException extends HutoolException { private static final long serialVersionUID = 1L; - public SPIException(final Throwable cause) { - super(ExceptionUtil.getMessage(cause), cause); + /** + * 构造 + * + * @param e 异常 + */ + public SPIException(final Throwable e) { + super(e); } + /** + * 构造 + * + * @param message 消息 + */ public SPIException(final String message) { super(message); } + /** + * 构造 + * + * @param messageTemplate 消息模板 + * @param params 参数 + */ public SPIException(final String messageTemplate, final Object... params) { - super(StrUtil.format(messageTemplate, params)); + super(messageTemplate, params); } + /** + * 构造 + * + * @param message 消息 + * @param cause 被包装的子异常 + */ public SPIException(final String message, final Throwable cause) { super(message, cause); } + /** + * 构造 + * + * @param message 消息 + * @param cause 被包装的子异常 + * @param enableSuppression 是否启用抑制 + * @param writableStackTrace 堆栈跟踪是否应该是可写的 + */ public SPIException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } + /** + * 构造 + * + * @param cause 被包装的子异常 + * @param messageTemplate 消息模板 + * @param params 参数 + */ public SPIException(final Throwable cause, final String messageTemplate, final Object... params) { - super(StrUtil.format(messageTemplate, params), cause); + super(cause, messageTemplate, params); } } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ClassDescTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ClassDescTest.java index 84ccf2326..6494b5f70 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ClassDescTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ClassDescTest.java @@ -12,8 +12,12 @@ package org.dromara.hutool.core.reflect; +import lombok.SneakyThrows; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Arrays; + import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -78,4 +82,32 @@ public class ClassDescTest { assertEquals("[[Ljava/lang/Object;", ClassDescUtil.nameToDesc(ClassDescUtil.getName(Object[][].class))); } + + @Test + @SneakyThrows + public void testGetDescriptor() { + // methods + Assertions.assertEquals("()I", ClassDescUtil.getDesc( + Object.class.getMethod("hashCode"), false)); + Assertions.assertEquals("()Ljava/lang/String;", ClassDescUtil.getDesc( + Object.class.getMethod("toString"), false)); + Assertions.assertEquals("(Ljava/lang/Object;)Z", ClassDescUtil.getDesc( + Object.class.getMethod("equals", Object.class), false)); + Assertions.assertEquals("(II)I", ClassDescUtil.getDesc( + Integer.class.getDeclaredMethod("compare", int.class, int.class), false)); + Assertions.assertEquals("([Ljava/lang/Object;)Ljava/util/List;", ClassDescUtil.getDesc( + Arrays.class.getMethod("asList", Object[].class), false)); + Assertions.assertEquals("()V", ClassDescUtil.getDesc( + Object.class.getConstructor(), false)); + + // clazz + Assertions.assertEquals("Z", ClassDescUtil.getDesc(boolean.class)); + Assertions.assertEquals("Ljava/lang/Boolean;", ClassDescUtil.getDesc(Boolean.class)); + Assertions.assertEquals("[[[D", ClassDescUtil.getDesc(double[][][].class)); + Assertions.assertEquals("I", ClassDescUtil.getDesc(int.class)); + Assertions.assertEquals("Ljava/lang/Integer;", ClassDescUtil.getDesc(Integer.class)); + Assertions.assertEquals("V", ClassDescUtil.getDesc(void.class)); + Assertions.assertEquals("Ljava/lang/Void;", ClassDescUtil.getDesc(Void.class)); + Assertions.assertEquals("Ljava/lang/Object;", ClassDescUtil.getDesc(Object.class)); + } } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ReflectUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ReflectUtilTest.java index 6872afc0a..92823ebbc 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ReflectUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/reflect/ReflectUtilTest.java @@ -111,25 +111,4 @@ public class ReflectUtilTest { } } - - @Test - @SneakyThrows - public void testGetDescriptor() { - // methods - Assertions.assertEquals("()I", ReflectUtil.getDescriptor(Object.class.getMethod("hashCode"))); - Assertions.assertEquals("()Ljava/lang/String;", ReflectUtil.getDescriptor(Object.class.getMethod("toString"))); - Assertions.assertEquals("(Ljava/lang/Object;)Z", ReflectUtil.getDescriptor(Object.class.getMethod("equals", Object.class))); - Assertions.assertEquals("(II)I", ReflectUtil.getDescriptor(Integer.class.getDeclaredMethod("compare", int.class, int.class))); - Assertions.assertEquals("([Ljava/lang/Object;)Ljava/util/List;", ReflectUtil.getDescriptor(Arrays.class.getMethod("asList", Object[].class))); - Assertions.assertEquals("()V", ReflectUtil.getDescriptor(Object.class.getConstructor())); - // clazz - Assertions.assertEquals("Z", ReflectUtil.getDescriptor(boolean.class)); - Assertions.assertEquals("Ljava/lang/Boolean;", ReflectUtil.getDescriptor(Boolean.class)); - Assertions.assertEquals("[[[D", ReflectUtil.getDescriptor(double[][][].class)); - Assertions.assertEquals("I", ReflectUtil.getDescriptor(int.class)); - Assertions.assertEquals("Ljava/lang/Integer;", ReflectUtil.getDescriptor(Integer.class)); - Assertions.assertEquals("V", ReflectUtil.getDescriptor(void.class)); - Assertions.assertEquals("Ljava/lang/Void;", ReflectUtil.getDescriptor(Void.class)); - Assertions.assertEquals("Ljava/lang/Object;", ReflectUtil.getDescriptor(Object.class)); - } }