web-dev-qa-db-ja.com

'super'キーワードによるジェネリックの境界

superをワイルドカードのみで使用でき、型パラメーターでは使用できないのはなぜですか?

たとえば、Collectionインターフェイスで、toArrayメソッドがこのように記述されていないのはなぜですか。

interface Collection<T>{
    <S super T> S[] toArray(S[] a);
}
57
mohsenof

誰も満足のいく答えを出していないので、正解は「正当な理由がない」のようです。

polygenelubricantsは、Java配列共分散で発生する悪いことの概要を示しました。これは、それ自体がひどい機能です。次のコードフラグメントを検討してください。

String[] strings = new String[1];
Object[] objects = strings;
objects[0] = 0;

この明らかに間違ったコードは、「スーパー」構造に頼らずにコンパイルされるため、配列の共分散を引数として使用しないでください。

ここで、名前付きタイプパラメーターにsuperを必要とする完全に有効なコードの例を示します。

class Nullable<A> {
    private A value;
    // Does not compile!!
    public <B super A> B withDefault(B defaultValue) {
        return value == null ? defaultValue : value;
    }
}

いくつかの素晴らしい使用法をサポートする可能性:

Nullable<Integer> intOrNull = ...;
Integer i = intOrNull.withDefault(8);
Number n = intOrNull.withDefault(3.5);
Object o = intOrNull.withDefault("What's so bad about a String here?");

後者のコードフラグメントは、Bを完全に削除するとコンパイルされないため、Bが実際に必要になります。

実装しようとしている機能は、型パラメーター宣言の順序を逆にして、super制約をextendsに変更すると簡単に取得できることに注意してください。ただし、これは、メソッドを静的メソッドとして書き直した場合にのみ可能です。

// This one actually works and I use it.
public static <B, A extends B> B withDefault(Nullable<A> nullable, B defaultValue) { ... }

重要なのは、このJava言語の制限は、他の方法で可能な便利な機能を実際に制限しており、醜い回避策が必要になる可能性があるということです。仮想にするためにwithDefaultが必要な場合はどうなるでしょうか。

ここで、polygenelubricantsが言ったことと相関させるために、ここではBを使用して、defaultValueとして渡されるオブジェクトのタイプを制限するのではなく(例で使用される文字列を参照)、呼び出し元の期待を制限します。返すオブジェクトについて。簡単なルールとして、要求するタイプではextendsを使用し、指定するタイプではsuperを使用します。

31
Rotsor

あなたの質問に対する「公式の」答えは Sun/Oracleバグレポート にあります。

BT2:評価

見る

http://lampwww.epfl.ch/~odersky/ftp/local-ti.ps

特にセクション3と9ページの最後の段落。サブタイプ制約の両側で型変数を許可すると、単一の最良の解がない一連の型方程式が生じる可能性があります。したがって、既存の標準アルゴリズムを使用して型推論を行うことはできません。そのため、型変数には「拡張」境界しかありません。

一方、ワイルドカードは推測する必要がないため、この制約は必要ありません。

@ ###。### 2004-05-25

はい;重要な点は、ワイルドカードは、キャプチャされた場合でも、推論プロセスの入力としてのみ使用されるということです。結果として、下限のあるもの(のみ)を推測する必要はありません。

@ ###。### 2004-05-26

問題があります。しかし、推論中にワイルドカードの下限で発生する問題とどのように異なるのかわかりません。例:

リスト<?スーパーナンバー> s;
ブールb;
.。
s = b? s:s;

現在、XがObjectを拡張するList <X>を条件式のタイプとして推測しています。これは、割り当てが不正であることを意味します。

@ ###。### 2004-05-26

悲しいことに、会話はそこで終わります。 (現在は死んでいる)リンクが指し示している紙は GJの推定型インスタンス化 です。最後のページを一瞥すると、要約すると次のようになります。下限が認められている場合、型推論によって複数の解が得られる可能性がありますが、いずれも principal ではありません。

11
Ben Schulz