質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

90.33%

  • Java

    14464questions

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

  • Eclipse

    1751questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

型引数で<?>だけ指定するメリット

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 405

lupus_dingo

score 257

お世話になっております。

listなどの変数を定義する際、
型引数を指定しないとeclipseで警告がでますが
それを回避する以外に<?>をつけるメリットはあるでしょうか?

ワイルドカードだけということは結局何が設定されてもよいということなので型引数を指定しない場合と同じに思えます。

ただ、警告が出たままは気持ちが悪いので、現状警告が出ている全てのlist変数の定義にワイルドカードをつけるべきなのか、また今後追加する際にワイルドカードをつけるべきなのか考えています。

※追記
型引数が指定できるクラスlistなどで型引数を省略して使用した場合とワイルドカード<?>のみを指定した場合で動作は変わらないが、ワイルドカードは付けるべきなのかという質問です。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yohhoy

    2018/04/21 09:09

    Genericsクラスやメソッドを自作する話ですか?それともライブラリ提供のGenericsクラスを利用する話でしょうか?具体例を追記された方が有用な回答が付きやすいと思います。

    キャンセル

  • lupus_dingo

    2018/04/21 10:38

    追記しました。

    キャンセル

回答 3

checkベストアンサー

+3

手元にあったEffective Java(第2版)を開けてみると、「項目23 新たなコードで原型を使用しない」というものがありました。

他の人の回答と重なりますが、List<T>というようなジェネリックな型に対して、Listの原型で変数や引数を宣言すると、ジェネリクスが持っていた型安全性をまるごと放棄することとなります。

List<?>では、このリストにaddする操作を書こうとすれば、型が決まらないのでコンパイルエラーになってくれます。原型のListにはaddも成功してしまい、宣言した型と違う要素を入れられるという形で型安全性が破綻します。ということで、原型の値を扱うべき場面はありません。

List<String> someList = new ArrayList<String>();
List<?> wildList = someList;
wildList.add(new Object()); // コンパイルエラーになる

List rawList = someList;
rawList.add(new Object()); // できてしまう

例外が2つほどありまして、

  • Classオブジェクトを取得したい場合は、原型を使ってList.classのように書く必要があります。List<Object>.classList<?>.classは動きません。
  • instanceofに与える型は、原型のListあるいは非境界ワイルドカードのList<?>である必要があります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/21 11:06

    > List<?>では、このリストにaddする操作を書こうとすれば、型が決まらないのでコンパイルエラーになってくれます。

    なんと、、
    そうだったんですね。。
    今までワイルドカードのみのリストにaddする機会がなかったのか疑問ですが…気付きませんでした。

    キャンセル

  • 2018/04/21 11:09

    あれ、違う、
    addが必要だからワイルドカードを指定出来ない可能性もあるということですよね。
    すみません。

    キャンセル

  • 2018/04/21 11:13

    「addが必要」な場合は、型が決まるはずです。<?>で宣言したものに対しては、「型パラメータに依存しない」操作しか行なえません。

    キャンセル

  • 2018/04/21 11:17

    (もちろん、nullは型に関係なく同じ値ですので、nullの入れられるListであれば、<?>でも.add(null)は可能です)

    キャンセル

  • 2018/04/21 11:20

    addが必要で型が不明ならList<Object>とかになるだろうしな

    キャンセル

  • 2018/04/21 11:21

    なるほど、今度試してみます。
    回答ありがとうございました。

    キャンセル

  • 2018/04/21 11:24

    swordoneさん
    あれ?そうですよね?なんか混乱してきました。。
    というか、元から<Object>を指定すればいいようなきがしてきました。。汗

    キャンセル

  • 2018/04/21 12:06

    List<Object>やList<String>(Stringしか入れられない)などの総称が、List<?>です。

    キャンセル

  • 2018/04/21 12:44

    それはわかっているのですが、Objectが全ての基底クラスという認識なので、
    <?>と<? extends Object>はどちらを指定しても同じでしょうか?

    キャンセル

  • 2018/04/21 13:15 編集

    はい、<? extends Object>としても<?>と意味は変わりません(List<Object>やList<String>を代入することもできます)。もちろん、どちらにも(null以外の)addはできません。

    キャンセル

  • 2018/04/21 13:26

    ありがとうございます。
    長々とすみませんでした。

    キャンセル

0

ジェネリクスを付けない書き方を未加工型と呼ぶそうです。
未加工型(raw型) - Java総称型メモ

互換性の為に許されているのであって、将来バージョンでは禁止になる可能性がある(Java言語仕様第3版4.8章『未加工型』)というくらいのシロモノらしい。

つまり未加工型は過去の遺物であり、今後に積極的に残す意味こそないため、<?>であれつけておくべきです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/21 10:32

    回答ありがとうございます。
    現状は警告以外に違いはないが、将来的にコンパイルエラーになるかもしれないんですね。
    付けるに越したことはないみたいですね。

    キャンセル

-1

<?>をつけることで型指定できるため予期しない型が入ってこないようになります。

ワイルドカードだけということは結局何が設定されてもよいということなので型引数を指定しない場合と同じに思えます。
それはすこし違っていてGenericsにすることによっていちいちオブジェクトの型変換をする必要がなくなります。これだけだとわかりにくいと思うのでここの記事が役に立ちます。
基本的に<?>の型指定はするべきですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/21 09:54

    <?>だと結局Object以外で使うなら型変換は必要ですし、「予期しない型が入ってこないようになる」ってのも大間違い。

    キャンセル

  • 2018/04/21 10:42

    回答ありがとうございます。
    質問の内容と回答がちょっとずれているかもしれません。

    具体的にいうと、
    List<?> list = new ArrayList<?>()
    の場合、型引数は指定してもしなくても動作としては問題ないのでわざわざ書かなくてもよいのでは?ということです。

    もちろん、このlistにはどんなオブジェクトが入るかは確定できません。

    キャンセル

  • 2018/04/21 10:45

    newのほうで<?>は無理では?

    キャンセル

  • 2018/04/21 10:50

    あ、すいません。
    あいまいなまま書いたので間違いです。
    いいたかったのは、
    List<?> list =◯◯
    の部分だけです。

    キャンセル

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

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Java

    14464questions

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

  • Eclipse

    1751questions

    Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。