Java:原始匿名类在其方法中丢失了泛型类型

Posted

技术标签:

【中文标题】Java:原始匿名类在其方法中丢失了泛型类型【英文标题】:Java: Raw anonymous class loses generic types in its methods 【发布时间】:2021-09-28 22:18:17 【问题描述】:

Java 编译器的这种行为让我有点不知所措。有人可以解释为什么会这样吗?考虑这个例子:

public static abstract class GenericClass<A extends GenericClass<A>> 
  protected abstract void method();
  protected <B> B getB(Class<B> bclass) 
    return null;
  

// ...
GenericClass<?> gc = new GenericClass() 
  @Override
  protected void method() 
    String s = getB(String.class); // does not compile
  
;
String s = gc.getB(String.class);  // compiles

由于new 中没有给出泛型参数,匿名类继承自原始类型GenericClass。即使方法getB 没有提及A,通用信息仍然丢失并且方法调用无法编译。为什么会这样?

此外,我无法为new 指定泛型参数的原因是因为它应该是匿名类本身,但我无法命名匿名类来传递它。我该如何正确地做到这一点?

【问题讨论】:

【参考方案1】:

存在原始类型是为了与泛型存在之前的代码兼容。它们被视为对所有通用事物的完全“退出”。如果您想要泛型,请不要使用原始类型。这就是语言设计的意图。

这里的解决方案是给类命名。是的,类可以出现在方法和其他语句块中;这样的东西被称为本地类。匿名类基本上是一个没有名字的本地类——本地类可以做任何匿名类可以做的事情。

String thisIsFine() 
    var cell = new Object()  String s; ; // example local variable to show local classes can access them
    class GenericImpl extends GenericClass<GenericImpl> 
       @Override
       protected void method() 
           cell.s = getB(String.class);
       
    
    new GenericImpl().method();
    return cell.s;

【讨论】:

本地课程可以解决问题,谢谢。虽然我不拥有实现 GenericClass 的代码,但我可以推荐这个解决方案。同时我仍然不太明白为什么原始类型会关闭 all 泛型,即使是那些不直接参与类类型定义的泛型。 @NebehrGudahtt 因为您通常不会在方法调用中指定泛型。预泛型代码可能包含GenericClass g = ...; g.getB(...) 之类的内容,并且在调用getB 时不会检查泛型。在泛型之后,调用g.getB 的语法不会改变,因为我们通常会保留推断的方法泛型。所以大多数时候语法不会向编译器发出信号,无论我们想要方法的原始类型还是泛型类型。因此,为了兼容性,调用的原始性必须选择与接收者的原始性相同。 但是为什么同样的调用在类方法之外起作用? @NebehrGudahtt 因为接收者的类型不同。 GenericClass 是原始类型,为了兼容性,all 上的 all 泛型必须删除,但 GenericClass&lt;?&gt; 是普通泛型类型,具有“正确”类型为一切。

以上是关于Java:原始匿名类在其方法中丢失了泛型类型的主要内容,如果未能解决你的问题,请参考以下文章

防止匿名类在 Java 中引用外部成员

java基础总结 -- 泛型 在类接口方法匿名类元组等使用 堆栈例子 商店模型

java基础总结 -- 泛型 在类接口方法匿名类元组等使用 堆栈例子 商店模型

java 如何调用局部内部类和匿名类

C#泛型委托,匿名方法,匿名类

Java编程:浅析泛型类型中的桥接方法