[解決済み] なぜワイルドカードジェネリックで複数のインターフェースを持つことができないのですか?
質問
Java の汎用型には直感に反するような性質がいろいろあることは知っています。特に理解できないものがあり、誰かが私に説明してくれることを期待しています。クラスやインターフェースの型パラメータを指定するとき、複数のインターフェースを実装しなければならないように、クラスやインターフェースを
public class Foo<T extends InterfaceA & InterfaceB>
. しかし、実際のオブジェクトをインスタンス化する場合、これはもううまくいきません。
List<? extends InterfaceA>
は問題ありませんが
List<? extends InterfaceA & InterfaceB>
はコンパイルに失敗します。次の完全なスニペットを考えてみましょう。
import java.util.List;
public class Test {
static interface A {
public int getSomething();
}
static interface B {
public int getSomethingElse();
}
static class AandB implements A, B {
public int getSomething() { return 1; }
public int getSomethingElse() { return 2; }
}
// Notice the multiple bounds here. This works.
static class AandBList<T extends A & B> {
List<T> list;
public List<T> getList() { return list; }
}
public static void main(String [] args) {
AandBList<AandB> foo = new AandBList<AandB>(); // This works fine!
foo.getList().add(new AandB());
List<? extends A> bar = new LinkedList<AandB>(); // This is fine too
// This last one fails to compile!
List<? extends A & B> foobar = new LinkedList<AandB>();
}
}
のセマンティクスは
bar
のセマンティクスはよく定義されているはずです。1つだけでなく2つの型の交差を許可することによって、型の安全性が失われるとは思えません。しかし、何か説明があるはずです。誰かそれが何であるか知っていますか?
どのように解決するのですか?
興味深いことに、インターフェイス
java.lang.reflect.WildcardType
は、ワイルドカードの arg に対して上限と下限の両方をサポートし、それぞれに複数の上限を含めることができるようです。
Type[] getUpperBounds();
Type[] getLowerBounds();
これは言語が許容する範囲をはるかに超えています。ソースコードに隠されたコメントがあります。
// one or many? Up to language spec; currently only one, but this API
// allows for generalization.
インターフェースの作者は、これは偶発的な制限であると考えているようです。
あなたの質問に対する定型的な答えは、ジェネリクスは現状ですでに複雑すぎる、ということです。
ワイルドカードが複数の上限を持つことを許可するには、仕様をスキャンして、システム全体がまだ動作することを確認する必要があります。
私が知っている1つの問題は、型推論になります。現在の推論ルールは、単に交差型を扱うことができません。制約を減らすためのルールはありません。
A&B << C
. もし、それを
A<<C
or
A<<B
現在の推論エンジンは、このような分岐を可能にするために、大きなオーバーホールをしなければなりません。しかし、本当に深刻な問題は、これは複数の解決策を可能にしますが、他のものより1つを好む正当な理由がないことです。
しかし、推論は型安全性に不可欠なものではありません。この場合、単に推論を拒否し、プログラマに明示的に型引数を埋めるように要求することができます。したがって、推論の難しさはインターセクション型に対する強い議論ではありません。
関連
-
NullPointerException - java.lang.
-
SLF4J: クラス・パスに複数のSLF4Jバインディングが含まれています。
-
1分でわかる!恋人の写真をIDEAの背景画像に設定する方法【おすすめ集
-
IDEAError:javaの依存性エラー。Annotation processing is not supported for module cycles...(アノテーション処理はモジュールサイクルではサポートされていません。
-
[解決済み] なぜJavaにはtransientフィールドがあるのですか?
-
[解決済み] Stringでswitch文が使えないのはなぜですか?
-
[解決済み] なぜJavaでは静的メソッドを抽象化できないのですか?
-
[解決済み] なぜC#は汎用属性型を禁止しているのですか?
-
[解決済み] Map.get(オブジェクトキー)が(完全な)ジェネリックでない理由は何でしょうか?
-
[解決済み】なぜPythonには符号関数がないのですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
アクセス制限です。タイプ 'Application' は API ではない(必要なライブラリに制限がある)。
-
Javaでよくある構文エラー
-
java -jarコマンドでパッケージを実行すると、無効または破損したjarfile xxxx.jarが表示される。
-
Javaジェネリックを1つの記事で
-
keytool error: java.io.FileNotFoundException: cacerts (アクセス拒否されました。)
-
List list = new ArrayList(); Error: ArrayList は型に解決できません。
-
java send https request prompt java.security.cert.について。
-
Junitのユニットテストエラー
-
IDEAError:javaの依存性エラー。Annotation processing is not supported for module cycles...(アノテーション処理はモジュールサイクルではサポートされていません。
-
WeChat小プログラム Bluetooth通信 Bluetoothモジュールデモ