4

次の2つのコードサンプルは同じロジックを表します。文字列がnullで、そのチェックに基づいて分岐するかどうかを確認します。最初のサンプルは安全にコンパイルされます。 2つめは、Javaジェネリックスに関連する型の不一致エラーを生成します。私の質問は十分に単純だと思われますが、それは私には分かりません。なぜコンパイラはこれら2つのステートメントを別々に扱いますか?ここで何が起こっているのか、どうすればわかりますか?なぜこれらの2つの条件はコンパイラによって異なって扱われますか?

/* compiles cleanly */ 
protected Collection<String> getUserRoles(Object context, 
     Set<String> mappableRoles) { 
    String cookieValue = extractCookieValue(context); 
    if (cookieValue != null) { 
     return securityService.getRolesForUser(cookieValue); 
    } else { 
     return Collections.emptySet(); 
    } 
} 


/* produces a compiler error */ 
protected Collection<String> getUserRoles(Object context, 
      Set<String> mappableRoles) { 
    String cookieValue = extractCookieValue(context); 
    return cookieValue == null ? Collections.emptySet() 
      : securityService.getRolesForUser(cookieValue); 
} 

Eclipseからコンパイラエラーが発生しました。要求されたよう

Type mismatch: cannot convert from Set<capture#1-of ? extends Object> to Collection<String>

は、ここでSecurityServiceインターフェイスの関連部分です。

public interface SecurityService { 
    public Set<String> getRolesForUser(String userId); 
} 
+1

securityService.getRolesForUser()の署名を投稿できますか? –

+0

が追加されました。インタフェースにはもう1つのメソッドがありますが、この例では呼び出されません。 –

答えて

7

問題は、コンパイラが3値演算子の戻り値をどのように解釈するかにあります。 part 15.25 of the JLSまたはquestionを参照してください(これは、オートボクシングによってさらに複雑になり、コンパイル時ではなく実行時にエラーが発生するため)。

これが正しい方向に向いていることを願っています。

+0

キャプチャの変換プロセスがその時の犯人だと私は思っています。そのドキュメントの大部分は私の頭をはるかに上回っていますが、少なくともジェネリックパズルを指し示すことができます。ありがとう。 –

5

Collections.emptySet()は、型指定のないSetを返すからです。代わりに、これを試してください:

Collections.<String>emptySet() 
+0

それはコンパイラエラーを削除しますが、なぜですか?私は、型推論が三項演算子ではなく、if/else構造体からできる理由に最も興味があります。 –

+0

謝罪 - 私は質問のその部分を逃した。 @Gevorgは私よりもはるかに優れた説明をするリンクを提供しています。 – mike9322

1

Collections.emptySet()は、第TType Inferenceのために使用される

public static final <T> Set<T> emptySet() 

として宣言されます。第2のgetUserRoles実装はJavaコンパイラが正しいタイプを検出するには複雑すぎます。それが問題の理由です。 回避方法:

protected Collection<String> getUserRoles(Object context, 
      Set<String> mappableRoles) { 
    String cookieValue = extractCookieValue(context); 
    Collection<String> a = null; 
    return cookieValue == null ? a = Collections.emptySet() 
      : securityService.getRolesForUser(cookieValue); 
} 
関連する問題