2012-05-07 5 views
5

これはjdk1.7.0_04です。Collections.emptyList()やJava汎用メソッドの奇妙な型推論動作ですか?

私は条件付きで自分の空のリストアップするという newよりも 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.emptyList(); 

をしかし、次のエラーを取得変更する必要があります:

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> 

は一体何この上で私は奇妙な(私には、とにかく)状況に遭遇しました??

ここで、何らかの奇妙な理由から、条件演算子を使用すると、型推論システムがの型パラメータが明示的に指定される必要があることを認識できなくなることが理解できます。しかし、なぜ(間違いなく冗長な)キャストの混乱物を挿入するのですか?

答えて

9

But why does inserting a (admittedly redundant) cast mess things up?

今、それ自体で表現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(); 
} 
5

、だけでなく、答えとしてリストアップしたかったです誰かがちょうど私のそばでこのことについて私に渡したもの。この件について、Sun/Oracleに提出されたbug reportへのリンクです。バグを評価している人は、何が起こっているのかについての有益な説明があります。抜粋:

The submitter here seems to assume that the type of a conditional expression is the type on the LHS of an assigment (List<String> in this case). This is not true: as stated by the JLS, the type of a conditional expression:

"The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7). "

It's important to understand why it's necessary to apply lub. Consider the following example:

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

In this case we have that LHS is of type Foo<? extends A> while the RHS is of type lub(Foo<B>, Foo<C>) , that is Foo<? extends B&C> .

関連する問題