5

これはjdk1.7.0_04です。

条件付きで自分の空のリストを作成するのCollections.emptyList()ではなく、使用しようとしていました。new

List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList();

ただし、次のエラーが発生します。

error: incompatible types
        List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList();
                                              ^
  required: List<String>
  found:    List<CAP#1>
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ? extends Object
1 error

私は物事を次のように変更する必要があることを理解することができました:

List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.<String>emptyList();

しかし、これに取り組んでいる一環として、私は(とにかく)奇妙な状況に遭遇しました:

List<String> alwaysEmpty = Collections.emptyList();

正常にコンパイルされますが、次のようになります。

List<String> alwaysEmpty = (List<String>) Collections.emptyList();

次のコンパイルエラーが発生します。

error: inconvertible types
        List<String> alwaysEmpty = (List<String>) Collections.emptyList();
                                                                       ^
  required: List<String>
  found:    List<Object>

一体何?

これで、おそらく何らかの奇妙な理由で、条件演算子を使用すると、型推論システムがemptyList()呼び出しの型パラメーターを認識できStringないため、明示的に指定する必要があることがわかります。しかし、なぜ(明らかに冗長な)キャストを挿入すると混乱するのでしょうか?

4

2 に答える 2

9

しかし、なぜ (確かに冗長な) キャストを挿入すると混乱するのでしょうか?

Collections.emptyList()自体は代入の対象ではないため、どの型引数を選択する必要があるのでしょうか? 型引数を指定するだけの方が良いです:

// Redundant here, but just as an example
List<String> alwaysEmpty = Collections.<String>emptyList();

条件演算子でも同じように機能します。

public static void main(String[] args) {              
    List<String> list = (args != null)
        ? Arrays.asList(args) : Collections.<String>emptyList();
}
于 2012-05-07T17:51:45.673 に答える
5

私はジョンの答えを受け入れるつもりですが、SOの外でこれについて誰かが私に渡したものを答えとしてリストしたかったのです。これは、まさにこのことについて Sun/Oracle に提出されたバグ レポートへのリンクです。バグを評価している人は、何が起こっているのかについて有益な説明をしています。抜粋:

ここでの送信者は、条件式の型が割り当ての LHS の型であると想定しているようです (List<String>この場合)。これは正しくありません: JLS で述べられているように、条件式のタイプ:

"条件式の型は、キャプチャ変換 (§5.1.10) をlub(T1, T2)(§15.12.2.7) に適用した結果です。"

lub を適用する必要がある理由を理解することが重要です。次の例を検討してください。

class A {}
class B extends A{}
class C extends A{}
class Foo<X> 
Foo<? extends A> l = b ? new Foo<B>() : new Foo<C>()

この場合、LHS は typeFoo<? extends A>であり、RHS は typeです。lub(Foo<B>, Foo<C>)つまり、 ですFoo<? extends B&C>

于 2012-05-07T17:59:14.007 に答える