簡體   English   中英

在Java中查找最具體的類

[英]Finding the most specific class in Java

我試圖為我的特定目的編寫某種異常處理程序。 我有一個班級列表。 讓我們說:

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 ....
         }
     }
}

此方法必須找到給定類型的最具體的類。 所以,如果我通過:

  • IllegalArgumentException,它必須找到IllegalArgumentException(不是RTE)。
  • RuntimeException,它必須找到RuntimeException
  • IllegalStateException,它還要查找RuntimeException(因為列表中沒有IllegalStateException)
  • 如果我添加了CustomException extends IllegalArgumentException並傳遞它,它必須返回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()來檢測運行時的當前類。 請考慮以下使用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()))添加了.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()返回運行時類的規范名稱。 .orElseGet()使用父類名對大多數特定類進行檢查,因此對於IllegalStateException.class您將按預期獲得RuntimeException.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 
{

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM