簡體   English   中英

繼承感知類到值映射以替換`instanceof`系列

[英]Inheritance-aware class to value map to replace series of `instanceof`

我正在尋找一些神奇的類似Map的實用程序,給定一個類型,返回與該類型或其最接近的超類型相關聯的值。 這是替換語句之類的

if (... instanceof A) return valueA;
else if (... instanceof B) return valueB;
...

我已經閱讀了Java中避免使用instanceof的答案,它提出了許多模式,特別是訪問者模式。 但是,由於目標是返回一個簡單的值,實現訪問者似乎是一種矯枉過正。

不幸的是,新的JDK類ClassValue也沒有資格,因為它不檢查超類型。

我想在我自己推出之前檢查這個實用程序是否存在於任何知名庫中。 實現應該是線程安全的,並且希望具有低於線性成本和插入值的數量。

地圖會做。 如果你想要類繼承,你需要向上走。

private final Map<Class<?>, Object> map = HashMap<>();

public void register(Class<?> clazz, Object value) {
    map.put(clazz, value);
}

public Object getValue(Class<?> clazz) {
    if (clazz == null) {
        return null;
    }
    Object value = map.get(clazz);
    if (value == null) {
        clazz = clazz.getSuperclass(); // May be null.
        return getValue(clazz);
    }
}

這對於int.classint.class

如果價值和階級之間存在關系:

public <T> T getValue(Class<T> clazz) {
    Object value = map.get(clazz);
    return clazz.cast(value);
}

您可以使用具有default方法的interface刪除大部分殘差來進行地圖查找。 你仍然需要以某種方式注冊每個類 - 我使用了static初始化器,你可能有一個更好的方法。

interface HasClassValue {

    // My big map.
    static final Map<Class<?>, Long> values = new HashMap<>();

    default Optional<Long> value() {
        Class<?> c = this.getClass();
        do {
            // Climb the class tree.
            Long value = values.get(c);
            if (value != null) {
                // Found it.
                return Optional.of(value);
            }
            // Up!
            c = c.getSuperclass();
        } while (c != null);
        // Not found.
        return Optional.empty();
    }

    // Maintain the map.
    public static void register(Class<?> c, long value) {
        values.put(c, value);
    }
}

static class X implements HasClassValue {

    static {
        HasClassValue.register(X.class, 100);
    }
}

static class Y extends X {

    static {
        HasClassValue.register(Y.class, 200);
    }
}

static class Z extends Y {
}

public void test() {
    X x = new X();
    Y y = new Y();
    Z z = new Z();
    System.out.println("X - " + x.value());
    System.out.println("Y - " + y.value());
    System.out.println("Z - " + z.value());
}

我用以下解決方案解決了我的項目中的問題。

GenericClass object = (GenericClass) Class.forName(specificClassName).newInstance();

我定義了一個GenericClassBase class )。 我有許多這些泛型類的具體實現。 Specific concrete class將加載className我作為參數傳遞。

暫無
暫無

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

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