2015-01-04 49 views
14

我創建了一個函數有用於我執行邏輯多個謂詞到過濾器和用於它們:這個表達式的目標類型必須是功能接口

@SafeVarargs 
public static <T> Stream<T> filter(Stream<T> source, Predicate<T>... predicates) { 
    return source.filter(Arrays.stream(predicates).reduce(predicates[0], Predicate::and)); 
} 

致電時:

filter(IntStream.range(0, 10).boxed(), x -> x % 2 != 0, x -> x%3 == 0).forEach(System.out::println); 

它工作正常,並打印3和9.但是,當我通過一個單一的謂詞,如:

filter(IntStream.range(0, 10).boxed(), x -> x % 2 != 0).forEach(System.out::println); 

我得到編譯錯誤:

The target type of this expression must be a functional interface 

這是爲什麼?

enter image description here 對於相關信息我使用Eclipse紅月版本1

+0

你可以發佈更多的代碼.... – Devavrata

+1

@Devvrat更多的代碼是什麼?一切已經發布了......方法簽名和body +調用會產生編譯錯誤。 – user2336315

+3

編譯是否在命令行上工作?我能夠在IntelliJ 14.0.2中運行你的兩個例子,並分別獲得了3,9,1,3,5,7,9。看起來它可能是一個Eclipse問題。 – mkobit

回答

7

這是編譯器的一個例子。爲了確定是否應該將參數的可變參數包裝到數組中或者只傳遞一個數組,它需要知道最後一個參數的類型,但是,在lambda表達式的情況下,它需要調用的方法簽名來確定類型。但是很明顯,由於lambda表達式不會是數組類型,因此javac可以毫無問題地編譯它。

一種可接受的變通。將過載方法:

@SafeVarargs 
public static <T> Stream<T> filter(Stream<T> source, Predicate<T>... predicates) { 
    return source.filter(
     Arrays.stream(predicates).reduce(predicates[0], Predicate::and)); 
} 
public static <T> Stream<T> filter(Stream<T> source, Predicate<T> predicate) { 
    return source.filter(predicate); 
} 

這將是一個可接受的工作周圍作爲同時提高用於單效率它不需要對主叫側進行任何更改在同一時間的情況下。


請注意,您的可變參數方法允許零參數,但如果以這種方式調用將會失敗。所以,你應該要麼再添超載:

public static <T> Stream<T> filter(Stream<T> source) { 
    return source; 
} 

或使該方法安全的無參數的情況:

@SafeVarargs 
public static <T> Stream<T> filter(Stream<T> source, Predicate<T>... predicates) { 
    return Arrays.stream(predicates).reduce(Predicate::and) 
       .map(source::filter).orElse(source); 
} 
2

NetBeans和Eclipse的在Java中解析lambda表達式地區的一些bug。他們正在慢慢修復,但直到他們,我發現最好的解決方法是: 1.聲明類型 2.如果不起作用,請使用塊 3.如果不起作用,創建一個匿名實現謂詞/函數等的對象。

這些讓你的代碼變得更加混亂,但它們在很多情況下都是必需的。

0

有時Eclipse中需要一個良好的醇」乾淨,所有的項目和問題的重建消失了。

相關問題