繁体   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