🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Generics

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

7003閲覧

ジェネリクスを持つクラスを継承したクラスに再度ジェネリクスを持たせた際にワイルドカード"?"が想定通りに機能しない

water_coffee

総合スコア7

Generics

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

3クリップ

投稿2019/12/01 10:25

編集2020/10/06 10:47

まずジェネリクス<T>を持つスーパークラスAを作成します。

A.java:Java

1public class A<T>{ 2}

次に、クラスAを継承して再度ジェネリクス<T>を持たせたサブクラスBを作成します。

B.java:Java

1public class B<T> extends A<T>{ 2}

このクラスBのClassオブジェクトB.classをワイルドカードClass<? extends A<?>>を引数にしたメソッドにB.classを渡すとなぜかコンパイルエラーが発生します。

main.java:Java

1public class main{ 2 3 public void test(Class<? extends A<?>> c) { 4 5 } 6 7 public void main() { 8 //コンパイルエラー 9 test(B.class); 10 11 } 12}

(追記)コンパイルエラーの内容は以下です。

Java

1The method test(Class<? extends A<?>>) in the type main is not applicable for the arguments (Class<B>)Java(67108979)

なぜこういう挙動になるのかがいまいち理解できません。
どなたか教えていただけないでしょうか?
Bクラスにジェネリクスがついていようがいまいが、BクラスはA<T>クラスのサブクラスだと思うのですが…。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2019/12/01 14:20

> B.classを渡すとなぜかコンパイルエラーが発生します そのコンパイルエラーの内容もご提示頂いたほうが良いように思います.
xebme

2019/12/01 22:15

Bの型 <T>はAからBに継承されると考えますか?Bの型 <T>がAの<T>に適用されると考えますか?
water_coffee

2019/12/01 23:39

>jimbeさん ご指摘ありがとうございます。エラー内容追記しました。 >xebmeさん 後者の認識です。
xebme

2019/12/03 04:09

後者の認識が回答だと思います。test(Class<? super B<?>> c)。理由を明確に説明できれば回答します。
guest

回答2

0

自己解決

一応、以下のように理解しました。

Bクラスが継承しているAクラスはジェネリクスTを持つが、そのジェネリクスTが継承先でどのように指定されているかはクラスオブジェクトからは判断できない。

Java

1B<T> extends A<String>

かもしれないし

Java

1B<T> extends A

かもしれない。

なので、

Java

1Class<? extends A<?>>

を引数の型にするとコンパイルエラーとなり、ダウンキャストの必要がある。
引数となるBクラスでジェネリクスをどのように指定しているか不明なため。

一方で、

Java

1Class<? super B<?>>

では、クラスBがジェネリクスを持つのはクラスBのクラスオブジェクトから見て判定可能、ダウンキャストの必要はない。

投稿2020/10/06 12:50

water_coffee

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

これだと再帰的な型境界になっていませんか?

Java

1Class<? extends A<?>>

B extends A<B>
のような。

型が一致しないエラーが起きるのは、その為かと思います。

投稿2019/12/03 03:44

yamamotosoft

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2019/12/03 06:43 編集

<T> void test(Class<T extends A<T>> c) このように記述すればおっしゃる通り再帰的型境界(?)になりますが、 ? extends A<?> と記述した場合は二つの?が独立したものとして扱われ再帰的にはならないと思います。
yamamotosoft

2019/12/03 09:28

間違った回答をしてしまい、申し訳ありませんでした。ご迷惑をおかけしました。
KSwordOfHaste

2019/12/03 14:00

yamamotosoftさん回答に指摘したものの・・・自分も正確な回答をする自信がなく。 genericsの仕様の理解不足を感じているところです orz
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問