簡體   English   中英

Java泛型-從“ capture#1 of?”到“ A”的未經檢查的轉換

[英]Java Generics - Unchecked cast from “capture#1 of ?” to “A”

我有2條警告:

  • 警告1: unchecked cast, required: A found: capture#1 of ?
  • 警告2: unchecked cast, required: A found: Congress

我知道該課程實際上是一個事件。

在“事件”是接口的情況下,展覽和國會均實現“事件”接口。

public static <A extends Event> A copy(A event) {
        Class<?> eventType = event.getClass(); // --> Warning 1
        return (A) eventType.getConstructor(eventType).newInstance(event);
    return event;
}

第二個警告:

public static <A extends Event> A create(EventType type) {
    if(type == EventType.CONGRESS){ 
        return (A) new Congress() // --> Warning 2
    }else(){
        return (A) new Exhibition() // --> Same as warning 2 but for Exibition
    }
}

現在的問題是:如何不使用以下命令解決這兩個警告:

@SuppressWarning("unchecked")

似乎您在濫用泛型。 如果方法決定返回哪種類型,則不應使用泛型。 當調用者決定返回哪種類型時,將使用泛型。

所以create應該是這樣的:

public static Event create(EventType type) {
    if(type == EventType.CONGRESS){ 
        return new Congress();
    }else {
        return new Exhibition();
    }
}

對於第一個警告,您可以執行以下操作。

public static <A extends Event> A copy(A event) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    return (A) event.getClass().getConstructor(event.getClass()).newInstance(event);

}

您可以通過將eventType聲明為Class<? extends A>來解決第一個警告Class<? extends A> Class<? extends A> 這使得強制轉換為A多余的。

如果您無法更改第一種方法的返回類型,則無法選擇不使用強制轉換來解決此編譯問題。 可以通過將方法的返回類型更改為Event來解決編譯問題。 如果將返回類型更改為Event ,則可以完全刪除通用參數:

public static Event copy(Event e)
        throws NoSuchMethodException,
            IllegalAccessException,
            InstantiationException,
            InvocationTargetException {
    Class<? extends Event> cls = e.getClass();
    return cls.getConstructor(cls).newInstance();
}

對於第二個警告,您也可以完全刪除該方法的通用類型:

public Event create(EventType type) {
    if (type == EventType.CONGRESS) {
        return new Congress();
    } else {
        return new Exhibition();
    }
}

這假定Congress extends EventExhibition extends Event

為什么要將此方法設為靜態方法?

public static <A extends Event> A copy(A event) {
        Class<?> eventType = event.getClass(); // --> Warning 1
        return (A) eventType.getConstructor(eventType).newInstance(event);
    return event;
}

您具有Event的實例,讓Event類能夠創建其自身的副本。

abstract class Event<E extends Event<E>> {
    public E createCopy(E toCopy);
}

class Exhibition extends Event<Exhibition> {
    // ...
    public Exhibition createCopy() {
        return new Exhibition(this); 
    }
}

您可以擺脫的第二個警告是將EventType調整為

public enum EventType {
    CONGRESS { public Event createEvent() { return new Congress(); }},
    EXHIBITION { public Event createEvent() { return new Exhibition(); }};

    public abstract Event createEvent();
}

這將導致

public static Event create(EventType type) {
    return type.createEvent();
}

如果確實有必要知道返回的事件的確切類型,那么此時您應該重新考慮設計。

我建議使用TypeTags aka ClassTags。 就像是:

public static <A extends Event> Optional<A> create(Class<A> classTag) {
    try {
        return Optional.of(classTag.newInstance());
    } catch (InstantiationException | IllegalAccessException e) {
        return Optional.empty();
    }
}

這樣稱呼它:

public static void main(String[] args) {
    Optional<Exhibition> e = create(Exhibition.class);
    e.ifPresent(System.out::println);
}

暫無
暫無

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

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