在 Java 中找到最具体的 class
Finding the most specific class in Java
我试图为我的特定目的编写某种异常处理程序。
我有一个 classes 的列表。比方说:
List<Class<? extends Throwable>> list = new LinkedList<>();
list.add(RuntimeException.class);
list.add(IllegalArgumentException.class);
现在,我想做:
public Class<? extends Throwable> findMostSpecific(Class<? extends Throwable> type) {
for (....) {
if (... WHAT TO PUT HERE ? .... ) {
return ....
}
}
}
此方法必须找到给定类型的最具体 class。所以如果我通过:
- IllegalArgumentException,它必须找到 IllegalArgumentException(不是 RTE)。
- RuntimeException,它必须找到RuntimeException
- IllegalStateException,它还必须找到 RuntimeException(因为 IllegalStateException 不在列表中)
- 如果我添加
CustomException extends IllegalArgumentException
并传递它,它必须 return IllegalArgumentException(不是 RTE 并且 CustomException 不在列表中,所以 IllegalArgumentException 是最具体的)
那么如何找到给定实例的最具体类型呢?可能吗?
在这里试一试:
public Class<? extends Throwable> findMostSpecific(Class<? extends Throwable> type) {
// we'll keep a reference to the most specific one here
Class<? extends Throwable> mostSpecific = null;
// here we iterate over your list of types
for (Class<? extends Throwable> tType : list) {
// well not even a subtype of tType so ignore it
if (!tType.isAssignableFrom(type)) {
continue;
}
if (mostSpecific == null || mostSpecific.isAssignableFrom(tType)) {
mostSpecific = tType;
}
}
return mostSpecific;
}
在这种情况下,您可以使用 Class.getCanonicalName()
在 运行 时间检测电流 class。考虑以下使用 Java Stream API 找到最佳候选者的示例测试用例:
import org.junit.Test;
import java.util.LinkedList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class ReflectionTest {
@Test
public void test() {
assertThat(findMostSpecific(IllegalArgumentException.class)).isEqualTo(IllegalArgumentException.class);
assertThat(findMostSpecific(RuntimeException.class)).isEqualTo(RuntimeException.class);
assertThat(findMostSpecific(IllegalStateException.class)).isEqualTo(RuntimeException.class);
assertThat(findMostSpecific(IllegalStateException.class)).isEqualTo(RuntimeException.class);
assertThat(findMostSpecific(CustomException.class)).isEqualTo(IllegalArgumentException.class);
}
public Class<? extends Throwable> findMostSpecific(Class<? extends Throwable> type) {
List<Class<? extends Throwable>> list = new LinkedList<>();
list.add(RuntimeException.class);
list.add(IllegalArgumentException.class);
return list.stream()
.peek(e -> System.out.println("e.getClass() == " + e.getClass()))
.filter(e -> type.getCanonicalName().equals(e.getCanonicalName()))
.findAny()
.orElseGet(() -> findMostSpecific((Class<? extends Throwable>) type.getSuperclass()));
}
public static class CustomException extends IllegalArgumentException {}
}
我特意添加了 .peek(e -> System.out.println("e.getClass() == " + e.getClass()))
以便您可以看到我们在这里获得了编译时信息:
e.getClass() == class java.lang.Class
e.getClass() == class java.lang.Class
e.getClass() == class java.lang.Class
Class.getCanonicalName()
另一方面 returns 运行 时代 class 的规范名称。 .orElseGet()
使用父 class 名称检查最具体的 class,因此对于 IllegalStateException.class
,您将按预期得到 RuntimeException.class
。当然,这只是一个可以完善和改进的示例代码(例如,不应为每个方法调用实例化带有 classes 的列表)。希望对你有帮助。
基于流的解决方案也可以包含两个简单的步骤:
- 根据给定的元素是否可分配来过滤流 class
- 计算剩余流的最大值
如图所示:
import java.util.Arrays;
import java.util.List;
public class MostSpecificClassFinder
{
public static void main(String[] args)
{
List<Class<?>> classes = Arrays.asList(
RuntimeException.class,
IllegalArgumentException.class
);
System.out.println(findMostSpecific(classes, IllegalArgumentException.class));
System.out.println(findMostSpecific(classes, RuntimeException.class));
System.out.println(findMostSpecific(classes, IllegalStateException.class));
System.out.println(findMostSpecific(classes, CustomException.class));
}
public static Class<?> findMostSpecific(List<Class<?>> classes, Class<?> type) {
return classes.stream()
.filter(c -> c.isAssignableFrom(type))
.max((c0, c1) -> c0.isAssignableFrom(c1) ? -1 : c1.isAssignableFrom(c0) ? 1 : 0)
.get();
}
}
class CustomException extends IllegalArgumentException
{
}
我试图为我的特定目的编写某种异常处理程序。 我有一个 classes 的列表。比方说:
List<Class<? extends Throwable>> list = new LinkedList<>();
list.add(RuntimeException.class);
list.add(IllegalArgumentException.class);
现在,我想做:
public Class<? extends Throwable> findMostSpecific(Class<? extends Throwable> type) {
for (....) {
if (... WHAT TO PUT HERE ? .... ) {
return ....
}
}
}
此方法必须找到给定类型的最具体 class。所以如果我通过:
- IllegalArgumentException,它必须找到 IllegalArgumentException(不是 RTE)。
- RuntimeException,它必须找到RuntimeException
- IllegalStateException,它还必须找到 RuntimeException(因为 IllegalStateException 不在列表中)
- 如果我添加
CustomException extends IllegalArgumentException
并传递它,它必须 return IllegalArgumentException(不是 RTE 并且 CustomException 不在列表中,所以 IllegalArgumentException 是最具体的)
那么如何找到给定实例的最具体类型呢?可能吗?
在这里试一试:
public Class<? extends Throwable> findMostSpecific(Class<? extends Throwable> type) {
// we'll keep a reference to the most specific one here
Class<? extends Throwable> mostSpecific = null;
// here we iterate over your list of types
for (Class<? extends Throwable> tType : list) {
// well not even a subtype of tType so ignore it
if (!tType.isAssignableFrom(type)) {
continue;
}
if (mostSpecific == null || mostSpecific.isAssignableFrom(tType)) {
mostSpecific = tType;
}
}
return mostSpecific;
}
在这种情况下,您可以使用 Class.getCanonicalName()
在 运行 时间检测电流 class。考虑以下使用 Java Stream API 找到最佳候选者的示例测试用例:
import org.junit.Test;
import java.util.LinkedList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class ReflectionTest {
@Test
public void test() {
assertThat(findMostSpecific(IllegalArgumentException.class)).isEqualTo(IllegalArgumentException.class);
assertThat(findMostSpecific(RuntimeException.class)).isEqualTo(RuntimeException.class);
assertThat(findMostSpecific(IllegalStateException.class)).isEqualTo(RuntimeException.class);
assertThat(findMostSpecific(IllegalStateException.class)).isEqualTo(RuntimeException.class);
assertThat(findMostSpecific(CustomException.class)).isEqualTo(IllegalArgumentException.class);
}
public Class<? extends Throwable> findMostSpecific(Class<? extends Throwable> type) {
List<Class<? extends Throwable>> list = new LinkedList<>();
list.add(RuntimeException.class);
list.add(IllegalArgumentException.class);
return list.stream()
.peek(e -> System.out.println("e.getClass() == " + e.getClass()))
.filter(e -> type.getCanonicalName().equals(e.getCanonicalName()))
.findAny()
.orElseGet(() -> findMostSpecific((Class<? extends Throwable>) type.getSuperclass()));
}
public static class CustomException extends IllegalArgumentException {}
}
我特意添加了 .peek(e -> System.out.println("e.getClass() == " + e.getClass()))
以便您可以看到我们在这里获得了编译时信息:
e.getClass() == class java.lang.Class
e.getClass() == class java.lang.Class
e.getClass() == class java.lang.Class
Class.getCanonicalName()
另一方面 returns 运行 时代 class 的规范名称。 .orElseGet()
使用父 class 名称检查最具体的 class,因此对于 IllegalStateException.class
,您将按预期得到 RuntimeException.class
。当然,这只是一个可以完善和改进的示例代码(例如,不应为每个方法调用实例化带有 classes 的列表)。希望对你有帮助。
基于流的解决方案也可以包含两个简单的步骤:
- 根据给定的元素是否可分配来过滤流 class
- 计算剩余流的最大值
如图所示:
import java.util.Arrays;
import java.util.List;
public class MostSpecificClassFinder
{
public static void main(String[] args)
{
List<Class<?>> classes = Arrays.asList(
RuntimeException.class,
IllegalArgumentException.class
);
System.out.println(findMostSpecific(classes, IllegalArgumentException.class));
System.out.println(findMostSpecific(classes, RuntimeException.class));
System.out.println(findMostSpecific(classes, IllegalStateException.class));
System.out.println(findMostSpecific(classes, CustomException.class));
}
public static Class<?> findMostSpecific(List<Class<?>> classes, Class<?> type) {
return classes.stream()
.filter(c -> c.isAssignableFrom(type))
.max((c0, c1) -> c0.isAssignableFrom(c1) ? -1 : c1.isAssignableFrom(c0) ? 1 : 0)
.get();
}
}
class CustomException extends IllegalArgumentException
{
}