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

Java: Raw anonymous class loses generic types in its methods

提问人:Nebehr Gudahtt 提问时间:7/21/2021 最后编辑:HTNWNebehr Gudahtt 更新时间:7/21/2021 访问量:124

问:

我对 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

因为 中没有给出泛型参数,所以匿名类继承自 原始类型 。即使该方法没有提及,泛型信息仍然会丢失,并且方法调用不会编译。为什么会这样?newGenericClassgetBA

此外,我无法指定泛型参数的原因是因为它应该是匿名类本身,但我无法命名匿名类来传递它。如何正确执行此操作?new

Java 泛型匿名 原始类型

评论


答:

4赞 HTNW 7/21/2021 #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;
}

评论

0赞 Nebehr Gudahtt 7/22/2021
本地课程可能会解决问题,谢谢。虽然我不拥有实现 GenericClass 的代码,但我可以推荐这个解决方案。同时,我仍然不太明白为什么原始类型会关闭所有泛型,即使是那些不直接参与类类型定义的泛型。
0赞 HTNW 7/22/2021
@NebehrGudahtt 因为通常不会在方法调用时指定泛型。预泛型代码可能包含类似的东西,并且它期望在调用 时不会进行泛型检查。在泛型之后,调用的语法不会改变,因为我们通常会推断方法泛型。因此,大多数时候,语法不会向编译器发出信号,表明我们是想要方法的原始类型还是泛型类型。因此,为了兼容,必须选择呼叫的原始性与接收方的原始性相同。GenericClass g = ...; g.getB(...)getBg.getB
0赞 Nebehr Gudahtt 7/22/2021
但是,为什么同样的调用在类方法之外起作用呢?
1赞 HTNW 7/22/2021
@NebehrGudahtt 因为接收器的类型不同。 是一个原始类型,为了兼容,必须擦除其所有方法上的所有泛型,但它是普通的泛型类型,并且具有所有内容的“正确”类型。GenericClassGenericClass<?>