[解決済み] なぜ配列は共変であり、ジェネリックは不変なのですか?
質問
Effective Java(ジョシュア・ブロック著)より。
- 配列は一般的な型と2つの重要な点で異なっています。まず、配列は共変量です。ジェネリックは不変である。
-
共変とは、XがYのサブタイプであれば、X[]もY[]のサブタイプになることを意味します。文字列がオブジェクトのサブタイプであるため、配列は共変性です。
String[] is subtype of Object[]
不変とは、XがYのサブタイプであるかどうかに関係なく、単純に意味します。
List<X> will not be subType of List<Y>.
私の疑問は、なぜJavaで配列を共変量にすることにしたのか、ということです。他にも以下のようなSOの投稿があります。 なぜ配列は不変で、リストは共変なのか? しかし、それらはScalaに焦点を合わせているようで、私はついていけません。
解決方法は?
経由 ウィキペディア :
JavaやC#の初期バージョンにはジェネリックス(別名パラメトリックポリモーフィズム)は含まれていませんでした。
このような環境では、配列を不変にすることで、有用なポリモーフィックプログラムが除外されます。 例えば、配列をシャッフルする関数や、2つの配列が等しいかどうかを
Object.equals
メソッドを要素に適用します。この実装は、配列に格納されている要素の正確な型に依存しないので、すべての型の配列に対して動作する単一の関数を書くことが可能であるはずです。型の関数を実装するのは簡単です。boolean equalArrays (Object[] a1, Object[] a2); void shuffleArray(Object[] a);
しかし,もし配列の型が不変であれば,これらの関数を呼び出すことができるのは
Object[]
. 例えば、文字列の配列をシャッフルすることはできません。そのため、JavaもC#も配列の型を共変的に扱います。例えば、C#では
string[]
のサブタイプです。object[]
であり、JavaではString[]
のサブタイプです。Object[]
.
これは、「なぜ配列は共変するのか」という問いに答えるもので、より正確には「なぜ でした。 配列が共変になる その時 ?quotです。
ジェネリックが導入されたとき、意図的に共変数にしなかったのは、以下の理由で指摘されています。 Jon Skeet氏による回答です。 :
いや、ア
List<Dog>
はList<Animal>
. で何ができるかを考えてみましょう。List<Animal>
- どんな動物でも加えることができる......猫も。さて、論理的に考えて、子犬の群れに猫を加えることができるでしょうか?絶対に無理です。// Illegal code - because otherwise life would be Bad List<Dog> dogs = new List<Dog>(); List<Animal> animals = dogs; // Awooga awooga animals.add(new Cat()); Dog dog = dogs.get(0); // This should be safe, right?
突然ですが、あなたは 非常に と戸惑う猫。
wikipedia の記事にある、配列を共変させるという当初の動機は、ジェネリックスには適用されなかったからです。 ワイルドカード は、共分散(および共分散)の表現を可能にするなど、さまざまな工夫がなされています。
boolean equalLists(List<?> l1, List<?> l2);
void shuffleList(List<?> l);
関連
-
スレッド "main "での例外をEclipseで解決 java.lang.Error: 未解決のコンパイル問題、コンパイラとパッケージの不整合
-
javaの実行中に「javaの例外が発生しました」と表示された場合はどうすればよいですか?
-
ファインバグタイプ
-
jd-gui Java Exceptionが発生しました。
-
Android Studio 3.1.2 で v4, v7 パッケージが見つからない シンボル 'AppCompatActivity' を解決できない
-
Intellij IDEAのエラー「CreateProcess error=2, system could not find specified file」に対する完璧な解決策です。
-
エラーの解決方法 jarfile XXX.jarにアクセスできません。
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] List<Dog> は List<Animal> のサブクラスですか?Java のジェネリックはなぜ暗黙のうちに多相性にならないのですか?
-
[解決済み] なぜJavaはThrowableの一般的なサブクラスを許さないのですか?
最新
-
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.
-
javaの実行中に「javaの例外が発生しました」と表示された場合はどうすればよいですか?
-
ファインバグタイプ
-
をインスタンス化することができません。
-
this()の呼び出しはコンストラクタ本体の最初の文でなければならない 例外解決と原因分析
-
JDKの設定時にjava.dllが見つからない、java SE Runtime Environmentが見つからない問題が発生しました。
-
VMの初期化中にエラーが発生しました java/lang/NoClassDefFoundError: java/lang/Object
-
spring-boot 401 このリソースにアクセスするには完全な認証が必要です エラー解決
-
javaコンパイル時のエラー:不正な文字 '\ufeff' に対する解決策です。
-
org.glassfish.jersey.servlet.ServletContainer