为什么<代码>列表
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
}
我不明白编译器的消息和编译错误的原因。
返回类型没有问题:
class Base {
<T> List<String> f() { return null; }
}
class Derived extends Base {
List<String> f() { return null; } // perfectly valid as return-type
}
问题是你的第一个声明不完整:
<T> void f(List<String> arg) {}de here
在返回类型之前定义的任何泛型通常都应该在方法的参数中使用。因为它没有被使用;对于不完整性,reason编译器首先将超类与子类中的方法视为类似,因为参数相同,但当它看到超类中涉及一个泛型,而子类中不涉及该泛型时,它无法确定它的确切含义。
返回类型不起任何作用,例如,尝试以下仍然会显示错误:
class Base {
<T> List<String> f(List<String> arg) { return null; }
}
class Derived extends Base {
List<String> f(List<String> arg) { return null; }
}
我建议完全遵循泛型语法,以免出现这种奇怪的行为。
哇,那是一个有趣的搜索。
这取决于一个方法何时重写另一个方法的确切说明。
相关部分在Java语言规范的§8.4.8.1覆盖(通过实例方法)中(我使用的是Java 14)。
在类C
中声明或由类C
继承的一个实例方法mC
,重写了类A
中声明的另一个方法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)
=
但是它们的擦除是一样的。擦除基本上删除所有类型参数。有关更复杂的细节,请参阅§4.6类型擦除。但是这里重要的是签名的擦除是:
无效f(List arg)
这违反了§8.4.8.3中关于覆盖和隐藏的要求:
如果类型声明T具有成员方法m1,并且存在在T中声明的方法m2或T的超类型,并且以下所有内容均为true,则为编译时错误:
m1和m2同名。
- m2可从T.
- m1的签名不是m2签名的子签名(§8.4.2)。
m1
或某些方法m1覆盖的签名(直接或间接)与
m2或某些方法
m2'覆盖的签名(直接或间接)具有相同的擦除。
当然,这给我们带来了一个问题:为什么使用
子签名
的奇怪定义?
这实际上在§8.4.2中进行了解释。方法签名:
子签名的概念旨在表示两个方法之间的关系,这两个方法的签名不完全相同,但其中一个方法可以覆盖另一个方法。具体来说,它允许签名不使用泛型类型的方法重写该方法的任何泛型版本。这一点很重要,这样库设计人员就可以独立于定义库的子类或子接口的客户端自由地生成方法。
在研究泛型时,我注意到泛型方法和泛型类型(类或接口)在类型引入语法上的一个差异使我感到困惑。 泛型方法的语法为 文件上说 为了彼此保持一致,我希望方法语法为 ,或者类型语法(for class)为,但事实显然并非如此。 为什么一个要介绍在前,另一个要介绍在后? 我主要以的形式使用泛型,并认为可能看起来很奇怪,但这是一个主观的参数,此外对于方法也是这样。您可以调用,类似于 在寻找技术解释时,我想在指
我想说得具体一点。我有一个名为Result的类和一个名为Result的派生类 这些类在方法中用作返回类型。为此,我创建了这个helper类: 正如您所看到的,上面的代码对于成功有两种返回类型,一种是如果您不想返回任何东西,另一种是如果您想返回一些东西,但是失败的结果永远不会返回什么东西。这是不必要的,只是一个错误消息。这使我想到以下问题:当我想创建一个可以使用返回类型返回Success,而不使用返
问题内容: 您认为可以创建类似的东西吗? 问题答案: 是的你可以。 用法示例:
问题总结:我想传递一个带有类型参数(如
问题内容: 如果在Java中创建泛型类(该类具有泛型类型参数),则可以使用泛型方法(该方法带有泛型类型参数)吗? 考虑以下示例: 正如您对通用方法所期望的那样,我可以使用任何对象调用的实例: 但是,如果我尝试使用 不 指定泛型类型的实例,则无论传入什么,我都会调用返回, 奇怪的是,如果返回类型是通用类,它将编译(例如(实际上,这可以解释-参见下面的答案)): 此外,如果输入通用类,即使仅使用通配符
如果在Java中创建泛型类(该类具有泛型类型参数),是否可以使用泛型方法(该方法采用泛型类型参数)? 考虑下面的例子: 正如您所期望的那样,对于任何对象,的实例,我都可以调用: 但是,如果我试图使用的实例而不指定泛型类型,那么调用将返回一个