2015-02-05 33 views
6

我一直只使用了Java 6和我現在趕上學習什麼用Java 8的新功能我在這裏讀這篇文章: http://www.drdobbs.com/jvm/lambda-expressions-in-java-8/240166764?pgno=2BiFunction引用可以傳遞給期望函數接口的方法嗎?

它說:

Java的API定義了java.util.function包中的幾個通用功能接口。接口之一,雙功能,描述了參數類型T和U和返回類型 R.您功能可以保存我們的字符串比較拉姆達在於 類型的變量:

雙功能排版 =(第一,第二) - > Integer.compare(first.length(),second.length());

但是,這並不能幫助您排序。有 是沒有Arrays.sort方法,想要一個BiFunction。如果您以前使用過功能編程語言,您可能會發現這種好奇心。但是對於Java程序員而言,這是非常自然的。一個接口如 比較器有一個特定的用途,而不僅僅是一個給定 參數和返回類型的方法。 Java 8保留了這種風格。當你想要 做一些lambda表達式時,你仍然想要保持表達式的目的,並且有一個特定的功能 接口。

然而,當我看到這個線程: How do you assign a lambda to a variable in Java 8?

這個問題的答案有建議做正是引用的段落說你不能這樣做。

那麼,文章中的信息是不正確的,還是我在這裏誤讀了一些東西?

謝謝!

+2

你可以只分配相同的lambda來了'Comparator'和排序調用... –

回答

16

我沒有看到任何東西在鏈接的回答與文章相矛盾。

類型系統的規則規則適用於功能接口類型的對象。如果一個變量聲明爲BiFunction<String,String,Integer> bifunc,你將不會被允許將其傳遞到需要Comparator<String>因爲BiFunction<String,String,Integer>不是Comparator<String>一型的方法。

該功能類型遵循所有的一般規則,這一事實就是允許以最少的干擾被添加這一新功能。

如果你希望做一個ComparatorBiFunction的所有您需要做的就是添加::apply像這樣:

BiFunction<String,String,Integer> bifunc = (a,b) -> 
           Integer.compare(a.length(), b.length()); 

Arrays.sort(array, bifunc::apply); 
2

該文章是正確的,你不能基於BiFunction類型的對象進行排序,但總是可以使用Comparator。但是,嘿,他們都可以擁有相同的身體。例如:

private static void sort(Comparator<String> ls){ 
     Arrays.sort(someArray, ls); 
} 

Comparator<String> comp = (String f1, String f2) -> Integer.compare(f1.length(), f2.length()); 
sort(comp); 

BiFunction<String, String, Integer> func = (String f1, String f2) -> Integer.compare(f1.length(), f2.length()); 
sort((String f1, String f2) -> Integer.compare(f1.length(), f2.length())); //line-4 

sort(func) // compiler error 

高於線4,你可以通過一個lambda這是func完全相同。但是你仍然無法通過funcsort。在java8中的Lambdas是一些執行FunctionalInterface。函數接口根據其引用類型獲取它們的類型。多數民衆贊成在初始化相同的lambda如何可以是BiFunctionComparator

但是,一旦lambda被構造並獲得它的類型,那麼你不能改變它。因此,您不能通過BiFunction類型的func排序哪些預期Comparator

1

這篇文章是正確的。您不能指定例如BiFunctionComparator

有了這樣說,這great article Brian Goetz撰寫書面解釋了一個不錯的方式的問題。

當編譯器遇到一個lambda表達式,它首先降低(desugars)拉姆達身體成其參數列表,並返回型匹配,所述lambda表達式

所以,一拉姆達可以是一個方法desugared - 但這是什麼意思?那麼,基本上這意味着可以創建一個新的方法(可能)以某種方式匹配lamdba。

class A { 
    public void foo() { 
     List<String> list = ... 
     list.forEach(s -> { System.out.println(s); }); 
    } 
} 

上面的代碼將是到這樣的事情:

class A { 
    public void foo() { 
     List<String> list = ... 
     list.forEach([lambda for lambda$1 as Consumer]); 
    } 

    static void lambda$1(String s) { 
     System.out.println(s); 
    } 
} 

所以,在BiFunctionComparator的情況。所提供的拉姆達可以被分配給兩個:一旦一個lambda已被分配給一個類型(BiFunctionComparator),那麼它不能被重新分配,即使lambda表達式匹配

// Assign the lambda to a BiFunction 
BiFunction<String, String, Integer> b1 = 
     (first, second) -> Integer.compare(first.length(), second.length()); 

// Assign the lambda to a Comparator 
Comparator<String> c1 = 
     (first, second) -> Integer.compare(first.length(), second.length()); 

// But, once the lambda has been assigned to a type you can not reassign it 
BiFunction<String, String, Integer> b2 = c1; // <-- Error 

注。

+0

使用它時,你拿過來的代碼段,你應該從這個老本文以他們更新到實際的API的機會。什麼叫'座'當時已經成爲消費者''。對於不瞭解歷史的讀者而言,堅持使用舊名稱可能會讓人困惑。 – Holger

+0

@霍爾再次,謝謝。更新了答案。 – wassgren

相關問題