2015-10-12 15 views
7

Il seguente codice si compila bene in IntelliJ ed Eclipse, ma il compilatore JDK 1.8.0_25 si lamenta. Innanzitutto, il codice.errato tipo restituito nell'espressione lambda

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); 
    } 
} 

L'uscita da javac 1.8.0_25 è:

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 

Quando sostituisco ? super E con semplicemente E, JDK compila con successo.

Quando sostituisco filter(MyPredicate con filter(Predicate, JDK viene compilato correttamente.

Dato che funziona con JDK 1.8.0_60, ho il sospetto che si tratti di un errore del compilatore.

Eventuali dettagli su ciò che ha causato questo e quando è stato risolto?

+2

sì, anch'io credo che sia un bug del compilatore.prova il filtro '((Booleano b) -> b))' ' – ZhongYu

risposta

6

Se un'espressione lambda appare in un tipo di destinazione con caratteri jolly (come nella maggior parte dei casi)

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

sorge la domanda - qual è il tipo di espressione lambda; in particolare, il tipo di b.

Naturalmente, ci potrebbero essere molte scelte a causa dei caratteri jolly; per esempio. potremmo scegliere esplicitamente

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

Tuttavia, implicitamente, b deve dedurre come Boolean. Questo ha senso dal momento che il consumatore dovrebbe essere alimentato solo con Boolean comunque.

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

Se T è un tipo di interfaccia funzionale jolly-parametrizzato e l'espressione lambda è implicitamente tipizzato, quindi il tipo di destinazione terra è la parametrizzazione non carattere jolly di T

(Questo probabilmente si presume che i caratteri jolly siano usati correttamente varianza-saggio sul tipo di destinazione, potremmo trovare alcuni esempi esilaranti se l'ipotesi non regge)

1

<? super E> include Object, che non è un Boolean. cioè

MyPredicate<? super E> 

Potrebbe essere un

MyPredicate<Object> 

e non è possibile restituire un Object come boolean.

provare a modificare le lambda a:

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

che compilare ed eseguire senza errori non importa il tipo di flusso, ma tornerà true per gli elementi che sono trueBoolean valori.

+3

no - mentre il tipo di destinazione è' Predicato ', il tipo di espressione lambda dovrebbe essere' Predicato '. (JLS # 12.27.3). Pertanto 'b' ha un tipo statico di' Boolean' – ZhongYu

Problemi correlati