Java:原始匿名 class 在其方法中丢失了通用类型
Java: Raw anonymous class loses generic types in its methods
我对 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
中没有给出通用参数,所以匿名 class 继承自原始类型 GenericClass
。即使方法 getB
没有提到 A
,通用信息仍然会丢失,并且方法调用不会编译。为什么会这样?
此外,我无法为 new
指定通用参数的原因是因为它应该是匿名 class 本身,但我无法将匿名 class 命名为交上来。我该如何正确执行此操作?
原始类型的存在是为了与泛型存在之前的代码兼容。他们被视为对所有通用事物的完全“选择退出”。如果你想要泛型,不要使用原始类型。这就是语言设计的意图。
这里的解决方法是命名class。是的,classes 可以出现在方法和其他语句块中;这样的东西叫做本地classes。匿名 class 基本上是没有名字的本地 class — 本地 classes 可以做任何匿名 classes 可以做的事情。
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;
}
我对 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
中没有给出通用参数,所以匿名 class 继承自原始类型 GenericClass
。即使方法 getB
没有提到 A
,通用信息仍然会丢失,并且方法调用不会编译。为什么会这样?
此外,我无法为 new
指定通用参数的原因是因为它应该是匿名 class 本身,但我无法将匿名 class 命名为交上来。我该如何正确执行此操作?
原始类型的存在是为了与泛型存在之前的代码兼容。他们被视为对所有通用事物的完全“选择退出”。如果你想要泛型,不要使用原始类型。这就是语言设计的意图。
这里的解决方法是命名class。是的,classes 可以出现在方法和其他语句块中;这样的东西叫做本地classes。匿名 class 基本上是没有名字的本地 class — 本地 classes 可以做任何匿名 classes 可以做的事情。
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;
}