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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

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

Eclipse

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

Q&A

解決済

3回答

372閲覧

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

lupus_dingo

総合スコア257

Java

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

Eclipse

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

0グッド

0クリップ

投稿2018/04/20 23:49

編集2018/04/21 01:38

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

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

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

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

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

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

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

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

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

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

yohhoy

2018/04/21 00:09

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

回答3

0

ベストアンサー

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

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

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

java

1List<String> someList = new ArrayList<String>(); 2List<?> wildList = someList; 3wildList.add(new Object()); // コンパイルエラーになる 4 5List rawList = someList; 6rawList.add(new Object()); // できてしまう

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

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

投稿2018/04/21 01:54

編集2018/04/21 01:57
maisumakun

総合スコア145121

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

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

lupus_dingo

2018/04/21 02:06

> List<?>では、このリストにaddする操作を書こうとすれば、型が決まらないのでコンパイルエラーになってくれます。 なんと、、 そうだったんですね。。 今までワイルドカードのみのリストにaddする機会がなかったのか疑問ですが…気付きませんでした。
lupus_dingo

2018/04/21 02:09

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

2018/04/21 02:13

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

2018/04/21 02:17

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

2018/04/21 02:20

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

2018/04/21 02:21

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

2018/04/21 02:24

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

2018/04/21 03:06

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

2018/04/21 03:44

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

2018/04/21 04:15 編集

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

2018/04/21 04:26

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

0

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

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

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

投稿2018/04/21 00:48

編集2018/04/21 00:53
swordone

総合スコア20649

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

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

lupus_dingo

2018/04/21 01:32

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

0

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

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

それはすこし違っていてGenericsにすることによっていちいちオブジェクトの型変換をする必要がなくなります。これだけだとわかりにくいと思うのでここの記事が役に立ちます。
基本的に<?>の型指定はするべきですね。

投稿2018/04/20 23:59

Nippun

総合スコア1147

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

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

swordone

2018/04/21 00:54

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

2018/04/21 01:42

回答ありがとうございます。 質問の内容と回答がちょっとずれているかもしれません。 具体的にいうと、 List<?> list = new ArrayList<?>() の場合、型引数は指定してもしなくても動作としては問題ないのでわざわざ書かなくてもよいのでは?ということです。 もちろん、このlistにはどんなオブジェクトが入るかは確定できません。
swordone

2018/04/21 01:45

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

2018/04/21 01:50

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問