2015-10-12 15 views
7

次のコードはIntelliJとEclipseではうまくコンパイルされますが、JDKコンパイラ1.8.0_25ではエラーが発生します。まず、コード。ラムダ式の悪質な戻り型

import java.util.function.Predicate; 

public abstract class MyStream<E> { 

    static <T> MyStream<T> create() { 
    return null; 
    } 

    abstract MyStream<E> filter(MyPredicate<? super E> predicate); 

    public interface MyPredicate<T> extends Predicate<T> { 

    @Override 
    boolean test(T t); 
    } 

    public void demo() { 
    MyStream.<Boolean> create().filter(b -> b); 
    MyStream.<String> create().filter(s -> s != null); 
    } 
} 

のjavac 1.8.0_25からの出力は次のとおりです。私は単にE? super Eを交換した場合

MyStream.java:18: error: incompatible types: incompatible parameter types in lambda expression 
    MyStream.<Boolean> create().filter(b -> b); 
            ^
MyStream.java:18: error: incompatible types: bad return type in lambda expression 
    MyStream.<Boolean> create().filter(b -> b); 
              ^
    ? super Boolean cannot be converted to boolean 
MyStream.java:19: error: bad operand types for binary operator '!=' 
    MyStream.<String> create().filter(s -> s != null); 
              ^
    first type: ? super String 
    second type: <null> 
MyStream.java:19: error: incompatible types: incompatible parameter types in lambda expression 
    MyStream.<String> create().filter(s -> s != null); 
            ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 
4 errors 

、JDKが正常にコンパイルされます。

​​をfilter(Predicateに置き換えると、JDKは正常にコンパイルされます。

JDK 1.8.0_60と動作するので、コンパイラのバグだと思われます。

これを引き起こした原因と修正された原因についての詳細はありますか?

+2

はい、あまりにもコンパイラのバグだと思います。'filter((Boolean b) - > b))' – ZhongYu

答えて

6

ラムダ式は、(ほとんどの場合のように)ワイルドカードでのターゲットタイプに表示された場合

Consumer<? super Boolean> consumer = b->{...} 

疑問が生じる - ラムダ式のタイプは何ですか。特に、タイプはbです。

もちろん、ワイルドカードのために多くの選択肢があります。例えば我々は明示しかし、暗黙のうちに、bBooleanと推測されるべき

Consumer<? super Boolean> consumer = (Object b)->{...} 

を選択することができます。とにかく消費者にはBooleanしか与えられないので、これは理にかなっています。

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3

Tワイルドカードパラメータ化機能インタフェースタイプおよびラムダ式が暗黙的に型付けされた場合は、地上目標タイプはT

の非ワイルドカードパラメータである

(これおそらく、ワイルドカードが目的の型で適切に分散的に使用されていると仮定します;仮定が成り立たない場合は面白い例があります)

1

<? super E>は、BooleanではないObjectを含みます。すなわち

MyPredicate<? super E> 

MyPredicate<Object> 

のだろうと、あなたはbooleanとしてObjectを返すことができません。

はあなたにラムダを変更してみてください:コンパイルしてストリームの種類を重要ではありませエラーなしで実行されます

MyStream.<Boolean> create().filter(b -> Boolean.TRUE.equals(b)); 

が、trueBoolean値である要素のためtrueを返します。

+3

いいえ - ターゲットタイプが 'Predicate <?スーパーブール値> '、ラムダ式の型は'述語 'でなければなりません。 (jls#12.27.3)。したがって、 'b'は静的型' Boolean'を持っています – ZhongYu

関連する問題