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

马科迈耶

有人可以解释一下,为什么<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

正确答案后更新:

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

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

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

javac -Xlint:unchecked ....
谐振

您可以找到答案是JLS的4.8节

未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.8节,第9.4节)或非静态字段(第8.3节)M的类型是对其类型的擦除原始类型C的静态成员的类型与对应于C的泛型声明中的类型相同。

如果创建通用类的实例而没有为其提供通用类型,则该实例将成为原始类型而且,由于JLS的这一部分,其所有(非继承)字段也都将被擦除。因此,就好像您声明接口是这样的:

interface B{
    List listOfStrings();
}

这会导致您看到错误。List即使您显式指定了返回的泛型类型,该类型也将被擦除。这就是为什么应始终避免使用原始类型的原因之一。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如果未指定类型参数,为什么Java泛型原始类会擦除对象的所有泛型?

来自分类Dev

如果泛型支持子类型化,会丢失哪种类型的安全性?

来自分类Dev

使用泛型时失去类型安全性

来自分类Dev

使用类型安全性定义打字稿泛型

来自分类Dev

使用泛型时失去类型安全性

来自分类Dev

泛型中的类型安全

来自分类Dev

泛型类中的方法不返回指定的类型。为什么?

来自分类Dev

泛型参数丢失类型安全性上的类型扩展

来自分类Dev

非泛型方法是否可以返回泛型类型?

来自分类Dev

使用泛型+联合类型从类中实现抽象方法时,类型安全性问题[Typescript]

来自分类Dev

返回泛型类型的泛型方法

来自分类Dev

泛型方法和泛型类中的类型推断

来自分类Dev

C#泛型并使用类型化方法中的非泛型版本

来自分类Dev

为什么将显式类型参数赋予非泛型方法或构造函数?

来自分类Dev

为什么我不能通过约束将派生泛型类型转换为基础非泛型类型?

来自分类Dev

为什么我不能(通过约束)将派生泛型类型转换为基础非泛型类型?

来自分类Dev

为什么在Java中可以将接口的泛型方法实现为非泛型?

来自分类Dev

在equals()方法中测试泛型类型

来自分类Dev

接口方法Java中的泛型类型

来自分类Dev

为什么Java泛型类型的推理在链式方法调用中中断?

来自分类Dev

为什么泛型结构不能具有在C#中指定泛型类型的静态成员?

来自分类Dev

为什么Scala不从泛型类型参数推断类型?

来自分类Dev

为什么Scala不从泛型类型参数推断类型?

来自分类Dev

调用具有多个泛型类型的泛型方法,而无需指定每个泛型类型

来自分类Dev

为什么在具有可比约束的泛型函数中丢失泛型类型信息?

来自分类Dev

泛型类型的扩展方法

来自分类Dev

泛型类型与扩展方法

来自分类Dev

与泛型类型方法的接口

来自分类Dev

如果我从泛型类派生非泛型类,类型会怎样?

Related 相关文章

  1. 1

    如果未指定类型参数,为什么Java泛型原始类会擦除对象的所有泛型?

  2. 2

    如果泛型支持子类型化,会丢失哪种类型的安全性?

  3. 3

    使用泛型时失去类型安全性

  4. 4

    使用类型安全性定义打字稿泛型

  5. 5

    使用泛型时失去类型安全性

  6. 6

    泛型中的类型安全

  7. 7

    泛型类中的方法不返回指定的类型。为什么?

  8. 8

    泛型参数丢失类型安全性上的类型扩展

  9. 9

    非泛型方法是否可以返回泛型类型?

  10. 10

    使用泛型+联合类型从类中实现抽象方法时,类型安全性问题[Typescript]

  11. 11

    返回泛型类型的泛型方法

  12. 12

    泛型方法和泛型类中的类型推断

  13. 13

    C#泛型并使用类型化方法中的非泛型版本

  14. 14

    为什么将显式类型参数赋予非泛型方法或构造函数?

  15. 15

    为什么我不能通过约束将派生泛型类型转换为基础非泛型类型?

  16. 16

    为什么我不能(通过约束)将派生泛型类型转换为基础非泛型类型?

  17. 17

    为什么在Java中可以将接口的泛型方法实现为非泛型?

  18. 18

    在equals()方法中测试泛型类型

  19. 19

    接口方法Java中的泛型类型

  20. 20

    为什么Java泛型类型的推理在链式方法调用中中断?

  21. 21

    为什么泛型结构不能具有在C#中指定泛型类型的静态成员?

  22. 22

    为什么Scala不从泛型类型参数推断类型?

  23. 23

    为什么Scala不从泛型类型参数推断类型?

  24. 24

    调用具有多个泛型类型的泛型方法,而无需指定每个泛型类型

  25. 25

    为什么在具有可比约束的泛型函数中丢失泛型类型信息?

  26. 26

    泛型类型的扩展方法

  27. 27

    泛型类型与扩展方法

  28. 28

    与泛型类型方法的接口

  29. 29

    如果我从泛型类派生非泛型类,类型会怎样?

热门标签

归档