0

我曾认为强制转换为无界通配符类型永远不会产生“未经检查的强制转换”警告,因为无界通配符类型已被具体化,因此安全完成强制转换所需的类型信息将在运行时出现,即“强制转换为泛型类”任何(未知)类型的实例。”

此方法在指示的行产生未经检查的强制转换警告:

    private static DateSerial.Metadata<?> metadataForName ( String className ) {

        Class<? extends DateSerial> cls;
        try {
            cls = Class.forName(className).asSubclass(DateSerial.class);
        } catch (ClassNotFoundException ex) {
            return null;
        }

-->     DateSerial.Metadata<?> result = (DateSerial.Metadata<?>) Kernel
            .obtainMetadata(cls)
            .orElse(null);
        return result;
    }

该方法obtainMetadata()返回一个Optional<T>where<T>是有界类型的参数<T extends DateSerial<T>>。正如您可以从上面的代码中推断出的,提供的类型参数<T>? extends DateSerial. 该方法的片段obtainMetadata如下所示:

static <D extends DateSerial<D>> Optional<DateSerial.Metadata<D>> 
            obtainMetadata ( Class<D> cls ) {

    Optional<Method> exe = Arrays
            .stream(cls.getDeclaredMethods())
                :
                :
            .findAny();

    DateSerial.Metadata<?> k;  // returned object must have type Metadata.class
    try {
        k = (DateSerial.Metadata<?>) exe    // checked cast
                .get().invoke(null);
    } 
    catch (... ex) { return Optional.empty(); }

    if (k == null || (k.getImplClass() != cls)) return Optional.empty();

    @SuppressWarnings("unchecked")
    DateSerial.Metadata<D> result = (DateSerial.Metadata<D>) k;
    return Optional.of(result);
}

此方法反射性地查找元数据对象访问器方法并调用它。调用的方法必须具有 Metadata.class 的返回类型。请注意,局部变量k是通过强制转换分配给无界通配符类型的。此行不生成警告。

在这个方法结束时,我已经证明元数据对象与提供的Class<D>参数具有相同的类型,因此我可以安全地转换为返回类型(警告被抑制,因为我已经证明它是安全的)。如果<D>? extends DateSerial,我希望返回类型是,Optional<Metadata<? extends DateSerial>>但它不是。由于我不清楚的原因,带有上述类型参数的返回类型是原始类型Optional

两个问题:

  1. 为什么强制转换为无界通配符类型会在 inmetadataForName()而不是 in生成警告obtainMetadata()
  2. 当 type 参数为时obtainMetadata()? extends DateSerial为什么该方法返回原始类型Optional
4

0 回答 0