2016-09-20 7 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 

しかし、私は§8.4.8.1でJLS8が言うことを確認しています:

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 'は 'List'の消去ではないので、引用した仕様ではサブシグニチャではありません。私はあなたが 'm1'と' m2'を混ぜ合わせたと思います。 – 4castle

+0

彼らは両方ともリスト 'にタイプ消去されているとは思われませんか? –

+1

これらは両方とも型リストから消去されていますが、あなたが引用した仕様は共通の消去があるかどうかではなく、サブクラスのメソッドがスーパークラスメソッドの消去であるかどうかについてです。親クラスに 'List 'があり、そのサブクラスに 'List'があった場合、あなたはうまくいくでしょう。 – 4castle

答えて

2

タイプ消去後には、List(好きな場合はList<Object>)しかないので、私はあなたが同じ消去

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?

のような一般的なParentを望んでいただけでは不十分だと思います。あなたが引用した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.

これは、消去が等しくなければならないというわけではありません。つまり、の署名はm2ののの署名の消去である必要があります。ここではm1の署名を消去していません。

+0

'クラス親{ ボイド方法(リストパラメータ){ } は} クラスの子供は、親延び{ ボイド方法(リストパラメータ){ } } M1のシグネチャが同じであるように'コンパイルべきこと㎡の署名の消去、しかしそれはしません。 –

+1

@JaimeHablutzel:m1とm2は別の方法です。 – user2357112

+0

m1とm2は適切なメソッドを参照していましたが、前のコメントの例の問題は 'List 'の型削除が 'List 'ではなく 'List'だけでした。'm1はm2'のシグネチャの消去と同じであり、それが正しく'クラス親{ ボイド方法(リスト FOO){ } } クラスの子供は、親{ ボイド法(延びて動作する場合、次の例では、明確リストバー){ } } 'です。 –

関連する問題