2016-09-20 57 views
1

下面的代码:为什么这个覆盖方法声明会产生编译错误?

class Parent { 
    public void method(List parameter){ 
    } 
} 

class Child extends Parent { 

    public void method(List<String> parameter) { 
    } 
} 

失败,出现以下错误编译:

Parent.java:12: error: name clash: method(List<String>) in Child and method(List) in Parent have the same erasure, yet neither overrides the other 
    public void method(List<String> parameter) { 
       ^
1 error 

但我检查JLS8在§8.4.8.1说:

An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:

...

The signature of mC is a subsignature (§8.4.2) of the signature of mA.

...

而且在§8.4.2中它说:

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

...

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

在这种情况下,原始和覆盖方法声明都具有相同的擦除,那么为什么编译失败?

+3

'列表'不是'List'的擦除,所以按照你所引用的规范,它不是一个子签名。我认为你有'm1'和'm2'混在一起。 – 4castle

+0

它们是不是都被认为是类型擦除到'List '?。 –

+1

它们都被擦除为“List”,但您引用的规范并不是关于它们是否具有共同的擦除,而是关于子类的方法是否是超类的擦除方法。如果父类具有'List '且子类具有'List',那么你会没事的。 – 4castle

回答

2

因为在删除之后,只有List(如果您愿意,可以使用List<Object>)。我想你想的通用Parent

class Parent<T> { 
    public void method(List<T> parameter){ 
    } 
} 

class Child extends Parent<String> { 
    public void method(List<String> parameter) { 
    } 
} 
+0

我不确定你的第一个陈述是否回答了这个问题,因为OP做了一个类似的例子,为什么它不应该是编译器错误。 – 4castle

+0

实际的父类属于遗留的库,但无论如何,我实际上并不在寻找解决方案,而是编译器行为的原因。 –

+0

@JaimeHablutzel因此,遗留代码(如你在这里)继续运行,增加了通用类型(几乎全部是编译时类型检查系统)。 –

2

And in this case both the original and the overriding method declarations have the same erasure, so why the compilation fails?

同一消失是不够的。再看看你引用的JLS部分:

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

...

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

这并不是说擦除必须相等。这就是说,m1的签名必须是删除m2的签名。我们没有在这里删除m1的签名。

+0

在这种情况下'类父{ 空隙方法(列表参数){ } } 类儿童延伸父{ 空隙方法(列表参数){ } }'应编译为M1的签名是相同的那删除m2的签名,但事实并非如此。 –

+1

@JaimeHablutzel:m1和m2是相反的方式。 – user2357112

+0

m1和m2指的是正确的方法,在我以前的评论中的例子的问题是“列表”的类型擦除不是“列表”而是“列表”。下面的例子阐明了当'm1是相同m2'的签名的擦除和它正常'类父{ 空隙方法(列表 FOO){ } } 类儿童延伸父{ 空隙方法(列表栏){ } } '。 –

相关问题