2017-02-12 10 views
1

しかし、f(オブジェクト)をf(文字列)またはf(整数)に変更すると、次のコードはコンパイルされません。 私は主題についての他の記事を読んだことがありますが、まだそれは得られません。どのような方法を使用するのがコンパイラには分かりません (新しいインスタンスA a = new B();)オーバーライドされたメソッドが型パラメータを指定しない場合、オーバーライドできないのはなぜですか?

public class SampleTester { 
    public static class A { 
     public void f(int x) { System.out.print("1"); } 
     public void f(Object x) { System.out.print("2"); } 
    } 
    public static class B extends A { 
      public <T> void f(T x) { System.out.print("3"); } //compiler error 
    } 
    public static void main(String[] args) { 
     A a = new A(); 
     B b= new B(); 
     a.f(3); 
     a.f("foo"); 
     b.f(3); 
     b.f("foo"); 
    } 
} 

、私はそれがまだコンパイルされませんObject tからT xを変更すると、その違いは何ですか?また、なぜAの関数をオーバーライドしないのか? 。問題は、ということである

public void f(int x) 
public void f(Object x) 
public <T> void f(T x) 

:(クラスBAを拡張し、従ってA中に存在するすべてのメソッドを継承型消去

+0

なぜこの質問が下落したのかわかりません。それはかなり良い質問IMOのようです。 – CKing

+0

私はdownvoteしなかったが、明白な質問は "だからエラーメッセージは何ですか?" *何かがコンパイルされない(またはコンパイルされますが、例外をスローする)という質問は、エラーの詳細を含める必要があります。 –

答えて

3

後に同じシグネチャを有し、両方これはBは、3つの方法を有することを意味しますf(T x)はコンパイル時にタイプ消去され、TObjectに置き換えられます。したがって、すでにObjectという引数を持つメソッドがあるため、重複したメソッドとなります。

これを修正するには、Object引数を取るメソッドを削除するか、Tの上限を指定します。 (私は今、あなたの質問に追加している)あなたのコメントに対処するために(たとえばT extends NumberTは、型消去中Numberに置き換えられるように)


:それはないですので

public <T> void f(Object x)がコンパイルされません。 public void f(Object x)の有効なオーバーライドはAです。

メソッドpublic <T> void f(Object x)はサブクラスに属し、a.<Integer>f(null);またはa.<String>f(null);というスーパークラスの参照を使用して呼び出すことができます。実行時にオーバーライドされたメソッドが解決されるため、コンパイル時にジェネリック型の消去が行われるため、をIntegerまたはStringに置き換えるかどうかコンパイラがコンパイル時に知る方法はありません。

まだ、コンパイラは<T>に置き換えすべきかを判断するために必要なすべての情報を持っているので、あなたはAにおける方法public <T> void f(Object x)と方法Bpublic void f(Object x)を持っていることを、このような方法を逆に合法です。

+0

しかし、TxをObject tに変更すると、それがコンパイルされるので、違いは何ですか? さらに、なぜAから関数をオーバーライドしないのですか? (どちらも型消去後に同じシグネチャを持ちます – DsCpp

+0

ここではコンパイルされません)をメソッドシグネチャから削除しないと、基本メソッドをオーバーライドするだけです。 –

+0

@DsCpp前の説明は不完全でした。あなたのレベルでのより深い理解。詳細は、編集を参照してください。 – CKing

関連する問題