[解決済み] コンストラクタの型引数は、型の前に置かれた場合、どのような意味を持つのでしょうか?
質問
私は最近、(私にとって)珍しいJavaの構文に出会いました。
List list = new <String, Long>ArrayList();
の位置関係に注目してください。
<String, Long>
型の引数の位置に注目してください...通常の型の後ではなく、前です。私はこの構文を見たことがないことを認めます。また、2つの型引数があることに注意してください。
ArrayList
には1つしかないのに、2つの型引数があることにも注意してください。
型の引数の位置は、型の後に置くのと同じ意味があるのでしょうか?そうでない場合、異なる位置づけは何を意味するのでしょうか?
のとき、なぜ2つの型引数を持つことが合法なのでしょうか?
ArrayList
は1つしかないのですか?
Angelika Langer やここなど、通常の場所を探しましたが、ANTLR プロジェクトの Java 文法ファイルの文法規則以外では、この構文についての言及はどこにも見つかりませんでした。
どのように解決するのですか?
汎用コンストラクタを呼び出す
これは非常に珍しいことですが、完全に有効な Java です。理解するためには、例えばクラスがジェネリックコンストラクタを持つ可能性があることを知る必要があります。
public class TypeWithGenericConstructor {
public <T> TypeWithGenericConstructor(T arg) {
// TODO Auto-generated constructor stub
}
}
ジェネリックコンストラクタでクラスをインスタンス化する場合、型の引数を明示する必要がないことの方が多いのではないでしょうか。例えば
new TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
現在
T
は明らかに
LocalDate
. しかし、Javaが型の引数を推論(推理)できない場合もあります。その時は、ご質問の構文を使って明示的に供給します。
new <LocalDate>TypeWithGenericConstructor(null);
もちろん、必要でない場合でも、可読性を高めるためや何らかの理由で提供することがあります。
new <LocalDate>TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
あなたの質問では
java.util.ArrayList
のコンストラクタを呼び出しているようです。このコンストラクタはジェネリックではありません。
ArrayList
クラス全体がそうであるだけで、それは別のものです)。Javaがなぜ型引数が使われないのに呼び出しで型引数を与えることができるのかについては、以下の私の編集をご覧ください。私のEclipseでは
警告
:
の非汎用コンストラクタArrayList()の未使用の型引数です。 引数でパラメータ化してはいけません。 Long>
しかし、これはエラーではなく、プログラムは正常に実行されます。
List
と
ArrayList
がありますが、これはまた別の話です)。
汎用クラスと汎用コンストラクタの比較
型引数の位置は、型引数の後に置くのと同じ意味ですか? と同じ意味を持つのでしょうか?そうでない場合、異なる位置づけは何を意味するのでしょうか? 位置づけは何を意味するのでしょうか?
いいえ、違います。通常の型引数/s
の後に
の後に、その型 (
ArrayList<Integer>()
) は
汎用クラス
. 型引数
の前に
は
コンストラクタ
.
この2つの形式は組み合わせることもできます。
List<Integer> list = new <String, Long>ArrayList<Integer>();
これでリストに格納されている
Integer
オブジェクトを保存していることがわかったので、これは少し正しいと言えるでしょう (私はまだ、意味のない
<String, Long>
は省きたいですね。)
ArrayListは1つしかないのに、なぜ2つの型引数があるのは合法なのでしょうか?
まず、型の前に型引数を与える場合、クラスではなくコンストラクタに正しい数を与える必要があるので、型引数の数とは関係ありません。
ArrayList
クラスが持っている型引数の数とは関係ありません。つまり、この場合、コンストラクタは型引数を取らないので、何も与えるべきではないということです(ジェネリックではありません)。いずれにせよ、いくつか指定した場合、それらは無視されるため、いくつ指定しても問題にはなりません。
なぜ無意味な型引数が許されるのですか?
リンクを提供してくれた@Slawに感謝しつつ編集します。Java はすべてのメソッド呼び出しで型引数を許可します。呼び出されたメソッドが一般的であれば、型引数が使用され、そうでなければ、それらは無視されます。たとえば
int length = "My string".<List>length();
そう、不条理なのです。Java Language Specification (JLS) は、サブセクション 15.12.2.1 でこの正当性を示しています。
<ブロッククオートこのルールは互換性の問題と置換可能性の原則に由来します。インターフェースやスーパークラスはサブタイプとは独立して生成されるので ジェネリックメソッドを非ジェネリックメソッドでオーバーライドすることができます。 を非ジェネリックメソッドでオーバーライドすることができます。ただし、オーバーライドする(非ジェネリック)メソッドは を含むジェネリックメソッドの呼び出しに適用可能でなければなりません。 型引数を明示的に渡す呼び出しを含む、ジェネリックメソッドの呼び出しに適用できなければなりません。そうでなければ、そのサブタイプは サブタイプはその生成されたスーパータイプに置き換えられない。
コンストラクタは直接オーバーライドできないので、この議論は成り立ちません。しかし、すでに複雑なルールをあまり複雑にしないために、同じルールにしたかったのでしょう。いずれにせよ、インスタンス化に関する15.9.3項と
new
は、15.12.2 を参照していることが多い。
リンク
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] C#のオートプロパティに初期値を与える最良の方法は何ですか?
-
[解決済み] C#でベースコンストラクタを呼び出す
-
[解決済み] Could not find or load main class "とはどういう意味ですか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] シンクロナイズド」とはどういう意味ですか?
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Java Error スレッド "AWT-EventQueue-0" で例外発生 java.lang.
-
undefinedeclipse エラー。この行に複数のアノテーションが見つかりました: - 文字列を型解決に解決できない
-
JavaMailのメール送信が失敗するケースとその説明の分析
-
Methodのinvokeメソッド実装のJavaリフレクション
-
スレッド "main" での例外 java.lang.ArrayIndexOutOfBoundsException: 1
-
javaでよく使われる英単語
-
java.lang.NoClassDefFoundError: org.apache.jasper.el.ELContextImpl クラスを初期化できませんでした。
-
スレッド "main" で例外発生 java.net.BindException: アドレスは既に使用中です。NET_Bind
-
java 例外。Javaツールの初期化
-
JSPで「リストが型解決できない!」の解決方法