質問: java ジェネリックスに関して 以前にも似たような質問をしたことがありますが、それに関しての質問です。 次のようなプログラムを書きました。 class a { public void display(t t) { system.out.println("a class"); } } public class test extends a { public void display(object t) { //問題の行 system.out.println("test class"); } public static void main(string[] args) { } } 上記の問題の行のところでエラーが出ました。 名前の競合: 型 test のメソッド display(object) は型 a の display(t) と同じ erasure を持っていますが、オーバーライドしません aのメソッドdisplay(t)のerasureはdisplay(object)になるので、display(t)は確かにtestのメソッドdisplay(object)と同じerasureを持っています。しかしそうなると、testのdisplay(object)のシグネチャがaのメソッドdisplay(t)のシグネチャのerasureと同じになるため、オーバーライドできることになると考えたのですが、コンパイル結果はエラーとなってしまいました。 どうしてオーバーライドできないのでしょうか。 例えば public class test extends a を public class test extends a にかえた場合はうまく行きました。従ってtをstringと指定しているところに問題があると思うのですが、どうしてコンパイルできないのでしょうか。 また、testのdisplay(object)をdisplay(string)にかえた場合(このとき、他の部分ははじめのプログラムと同じ)、aクラスのdisplay(t)をオーバーライドできました。今度はtestクラスのdisplay(string)とaクラスのdisplay(t)はerasureが同じではないので、オーバーライド等価ではない、従ってオーバーライドできないと思ったのですが、どうしてオーバーライドできるのでしょうか。
回答: public class test extends a { public void display(string t) { これなら、問題はない。あるいは、 public class sample extends a { public void display(string t) { とかでもokだ。aを、test extends aとして継承しているわけだから、は、でなければならない。をスーパークラスのに置き換えることはできない。だからdisplay(t t)はdisplay(object t)にはできない。 逆に、「extends a」として、display(string t)はできる。「tはobject」だが、stringはobjectとして扱うことができるから問題はない。 おそらく、aのtと、display(t t)のtは、どちらも同じクラスを示すものである、ということを忘れているんじゃないだろうか。何のために、(実際にそれが利用されているメソッドやフィールドなどではなく)クラスにが指定されるかといえば、それは「このクラスで、という(現時点では不特定だが、実行時には特定のクラスに決定される)クラスが使われる」ということを示すため。その「不特定なクラス」を実際に使用しているのがdisplayのtになる。 つまり、このdisplayのtは、class aで指定したtが実際に使われているところ、というわけになる。だから、両者は同じクラス指定となるのが当然だし、クラスで指定されたとあえて異なるクラスを指定するのであれば、そもそも「クラスのの指定が正しくされていない」ということになる。そもそもジェネリクスは「特定のクラスのみを受け付ける」ようにするためのものなわけだから、はジェネリクスとして無意味だ。 「なぜ、フィールドやメソッドだけでなく、クラスにもジェネリクスを指定するのか」を考えれば、自然と理解できるんじゃないかと思う。