java - 为什么泛型中未指定的类型会破坏非泛型方法的类型安全

标签 java generics

有人可以解释一下,为什么是一个简单的 <T>我的界面在编译时破坏了类型安全?请参阅以下示例:

public class GenericsMain {

public static void main(String[] args){
    A someA = new A() {
        @Override
        public List<String> listOfStrings() {
            return Arrays.asList("A");
        }
    };
    B someB = new B() {
        @Override
        public List<String> listOfStrings() {
            return Arrays.asList("B");
        }
    };
    List<Long> listOfLong = null;
    //listOfLong = someA.listOfStrings(); // compile error (expected)

    listOfLong = someB.listOfStrings(); // NO COMPILE ERROR. Why !?

    for(Long l : listOfLong){ // here I get ClastCastException of course.
         System.out.println(l);
    }
}

    interface A{
        List<String> listOfStrings();
    }

    interface B<T>{
        List<String> listOfStrings();
    }
}

同样有趣的是,如果 <T> 的类型指定后,编译器会再次正确地提示。所以看起来泛型也会影响非泛型方法声明!?

B<Integer> someBOfInteger = null;
listOfLong = someBOfInteger.listOfStrings(); // compiler complains correctly

正确答案后更新:

因此,如果需要使用泛型扩展类型,最好真正创建一个子类/子接口(interface)并在子类中添加泛型类型。因此,在上面的示例中,可以通过以下方式向 A 添加通用方法

interface C<T> extends A {
    T genericMethod(T p);  
}

此外,正如所引用的问题所示,使用编译器标志是一个好主意:

javac -Xlint:unchecked ....

最佳答案

你可以找到答案是section 4.8 of the JLS

The type of a constructor (§8.8), instance method (§8.8, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

如果您创建泛型类的实例而不为其指定泛型类型,则它会变成原始类型。而且,由于 JLS 的该部分,它的所有(非继承)字段也会被删除。所以就好像您将接口(interface)声明为这样:

interface B{
    List listOfStrings();
}

这会导致您看到的错误。即使您显式指定,返回的 List 的通用类型也会被删除。这是应始终避免原始类型的原因之一。

关于java - 为什么泛型中未指定的类型会破坏非泛型方法的类型安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37703206/

相关文章:

java - ArrayList<String> 类型中的方法 add(String) 不适用于arguments()

c# - 从 Dictionary<string, object> 中获取值而不拆箱?

generics - kotlin 泛型 : Cannot infer type parameter

c#泛型接口(interface)解决方案

java - 为什么这个通用作业不起作用?

mysql - Last_Insert_ID 和 OK PACKET

java - 如何将值添加到二维数组中的特定行

java - 首先调用构造函数或 onDraw()

java - 重用 javax.xml.ws.Service 对象安全吗?

java - 错误 : Could not find or load main class excel2JSON. excel