Java 为什么要列出<;字符串>;can';是否同时是基类泛型方法和派生类非泛型方法的参数?
为什么Java 为什么要列出<;字符串>;can';是否同时是基类泛型方法和派生类非泛型方法的参数?,java,generics,overriding,Java,Generics,Overriding,为什么List不能同时作为基类泛型方法和派生类非泛型方法的参数 class Base { <T> void f(List<String> arg) {} } class Derived extends Base { void f(List<String> arg) {} // above is compile ERROR: method f(List<String>) of type Derived has
List
不能同时作为基类泛型方法和派生类非泛型方法的参数
class Base {
<T> void f(List<String> arg) {}
}
class Derived extends Base {
void f(List<String> arg) {}
// above is compile ERROR: method f(List<String>) of type Derived has the same erasure
//as f(List<String>) of type Base but does not override it
}
类基{
void f(列表arg){}
}
类派生的扩展基{
void f(列表arg){}
//上面是编译错误:派生类型的方法f(List)具有相同的擦除
//作为Base类型的f(列表),但不覆盖它
}
我不明白编译器的消息和编译错误的原因
返回类型没有问题:
class Base {
<T> List<String> f() { return null; }
}
class Derived extends Base {
List<String> f() { return null; } // perfectly valid as return-type
}
类基{
列表f(){return null;}
}
类派生扩展基{
List f(){return null;}//作为返回类型完全有效
}
问题在于您的第一次声明不完整:
<T> void f(List<String> arg) {}de here
void f(List arg){}de在此
在返回类型之前定义的任何泛型通常都应该在方法的参数中使用。因为它没有被使用;对于不完整性,reason编译器首先将超类与子类中的方法视为类似,因为参数相同,但当它看到超类中涉及一个泛型,而子类中不涉及该泛型时,它无法确定它的确切含义
返回类型对此类型不起任何作用。例如,尝试以下操作仍将显示错误:
class Base {
<T> List<String> f(List<String> arg) { return null; }
}
class Derived extends Base {
List<String> f(List<String> arg) { return null; }
}
类基{
列表f(列表参数){returnnull;}
}
类派生扩展基{
列表f(列表参数){returnnull;}
}
我建议完全遵循泛型语法,以免出现这种奇怪的行为。哇,这是一个有趣的搜索 这取决于一个方法何时重写另一个方法的确切说明 相关部分在中(我使用的是Java14) 在类
C
中声明或由类C
继承的一个实例方法mC
,重写了类A
中声明的另一个方法mA
,如果以下所有条件均为真:
[……]
- mC的签名是mA签名的子签名(§8.4.2)
M
和N
,如果它们具有相同的名称、相同的类型参数(如有)(§8.4.4),则具有相同的签名,并且在将N
的形式参数类型调整为M
的类型参数后,具有相同的形式参数类型
方法m1
的签名是方法m2
签名的子签名,如果:
m2
具有与m1
相同的签名,或
m1
的签名与m2
签名的擦除(§4.6)相同
当m1
是m2
的子符号或m2
是m1
的子符号时,两个方法签名m1
和m2
是覆盖等价的
对于我们的案例,有两件事需要注意:
List
)。请注意,如果方法签名中没有泛型,即如果使用List
作为参数,或者如果List
仅出现在返回值中,则此更改void f(List arg)
这违反了以下章节的规定:
如果类型声明T有一个成员方法m1,并且存在一个在T或T的超类型中声明的方法m2,则这是一个编译时错误,并且以下所有情况均为真:
- m1和m2具有相同的名称
- m2可从T进入(§6.6)
- m1的签名不是m2签名的子签名(§8.4.2)
或某些方法m1
m1覆盖(直接或间接)的签名与
m2
或某些方法
m2`覆盖(直接或间接)的签名具有相同的擦除率
子签名
的奇怪定义
这实际上在以下章节中进行了解释:
子签名的概念旨在表示两个方法之间的关系,这两个方法的签名不完全相同,但其中一个方法可以覆盖另一个方法。具体来说,它允许签名不使用泛型类型的方法重写该方法的任何泛型版本。这一点很重要,这样库设计人员就可以独立于定义库的子类或子接口的客户端自由地生成方法
你明白是什么吗?是的。在运行时编译(字节码)后,到处都只有列表(在两个方法/类中)。尖括号内的类型边界仅用于编译期间的安全检查。但是我没有看到这里的问题——为什么相同的返回类型可以编译而作为参数——没有。我不知道这是为什么,但我可以想象它与
这个
有关。请注意,在这两种情况下,您都定义了一个类型参数t
(通过
),然后简单地将它放进去