Java 泛型方法执行隐式转换,而非泛型方法需要显式转换

Java 泛型方法执行隐式转换,而非泛型方法需要显式转换,java,generics,type-inference,unchecked-conversion,Java,Generics,Type Inference,Unchecked Conversion,这个问题是相关的。可以通过添加强制转换来执行未经检查的转换来解决原始问题。现在我有了以下代码: import java.util.EnumSet; class A { static enum E1 { X } private static <T extends Enum<T>> EnumSet<T> barEnum(Class<T> x) { return null; } pri

这个问题是相关的。可以通过添加强制转换来执行未经检查的转换来解决原始问题。现在我有了以下代码:

import java.util.EnumSet;

class A {
    static enum E1 {
    X
    }

    private static <T extends Enum<T>> EnumSet<T> barEnum(Class<T> x) {
        return null;
    }

    private static void foo1(EnumSet<E1> s, E1 e) {
        EnumSet<E1> x2 = barEnum((Class<E1>)e.getClass());
    }

    private static void foo2(EnumSet<E1> s) {
        EnumSet<E1> x = barEnum((Class<E1>)s.iterator().next().getClass());
    }
}
这显然包含未经检查的转换,并且编译时带有相应的警告。但是我没有将
getClass()
的结果显式地转换到
Class
中。由于
foo1()
是泛型方法
foo3()
的一个实例,我希望我也需要在这里添加强制转换。比较
foo1()
foo4()

    private static void foo4(EnumSet<E1> s) {
        EnumSet<E1> x = barEnum(s.iterator().next().getClass());
    }
private静态void foo4(枚举集){
EnumSet x=barEnum(s.iterator().next().getClass());
}

…这两者实际上是相似的(主要区别在于
foo1()
中的
e1e
参数)。但是
foo1()
会编译,但是
foo4()
不会编译。我觉得这是前后矛盾的。是否有允许泛型方法进行隐式转换的规则?

我的建议是阅读优秀的Java泛型常见问题解答:

恕我直言,它不会编译,因为静态方法不会继承泛型类的类型参数。然后,您试图获取参数化类型的运行时类信息,这将不起作用,因为Java在其泛型实现中使用擦除


Java中的泛型并不容易,一旦您超越了简单的集合等。这就是为什么FAQ是一个不可或缺的资源。

当我为获得的类提取一个变量并让IDE“修复”它所能修复的一切时,我得到了以下信息:

private static void foo4(Iterable<E1> s) {
    Class<? extends E1> aClass = s.iterator().next().getClass();
    EnumSet<E1>         x      = barEnum(aClass);
}

错误消失了,因为现在它接受了
Enum

的子类。发生了两件事。首先,如果您查看
getClass
的javadoc,它会说:


由于动态链接,实际的结果类型是
classe,甚至
final
类在运行时也可以有子类。所以具体的枚举是
final
应该无关紧要。这似乎是编译器无法推断
T
(因为原始调用没有有效的
T
)的问题。但是您的解决方案是正确的。不应该
getClass()
return
Class@shmosel是的,应该是这样。但这不是我必须在非泛型方法中将强制转换添加到
的原因吗,如上一段所述?@Jens是有道理的。您是否尝试将其分配给
EnumSet@shmosel我不知道你是什么意思?在
foo3
getClass
中,返回一个
Class@Jens我指的是
foo4
private static void foo4(Iterable<E1> s) {
    Class<? extends E1> aClass = s.iterator().next().getClass();
    EnumSet<E1>         x      = barEnum(aClass);
}
private static <T extends Enum<T>> EnumSet<T> barEnum(Class<? extends T> x) {