您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java8中lambda表達式的用法”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java8中lambda表達式的用法”吧!
只含有一個抽象方法的接口,被稱為函數式接口,例如Runnable、Comparator、EventHandler,可以使用lambda表達式來創建函數式接口的實例對象,例如:
Runnable task = () -> System.out.println("Hello Lambda!"); Comparator<String> comp = (first, second) -> Integer.compare(first.length(), second.length()); EventHandler<ActionEvent> handler = event -> System.out.println("Thanks for clicking!");
Java中的函數式接口,通常會使用 @FunctionalInterface 對接口類型進行注解。
lambda表達式廣義上的定義是:一個帶有參數的表達式。
在Java中,lambda表達式唯一的作用就是函數式接口的轉換,我們寫的lambda表達式,都是為了代替對函數式接口的實現,簡化編碼工作。
lambda表達式的參數列表對應函數式接口的抽象方法的參數列表,lambda表達式內容對應抽象方法實現的方法體。
(Type1 parameter1, Type2 parameter2, ..., TypeN parameterN) -> { statement1; statement2; ... statementN; return value; };
(String first, String second) -> Integer.compare(first.length(), second.length());
如果lambda表達式沒有參數,只寫一對小括號(),括號內留空;
如果一個lambda表達式的參數類型是可以被推導的,那么可以省略參數類型;例如:
Comparator<String> comp = (first, second) -> Integer.compare(first.length(), second.length());
如果一個lambda表達式只有一個參數,且該參數的類型是可以被推導的,那么可以省略參數類型和小括號,例如:
EventHandler<ActionEvent> handler = event -> System.out.println("Thanks for clicking!");
lambda表達式的參數列表本身也是要映射函數式接口抽象方法的參數列表的,所以我們可以像對待方法參數一樣對待lambda表達式參數,例如:添加final修飾、添加@NonNull注解等;
為了更容易地理解lambda,最好將lambda表達式想象成一個函數,而不是一個對象,并記住該函數可以被等價轉換成為一個函數式接口;
想要傳遞給其他代碼的操作已經有現成的實現方法了,想要復用已有的實現,例如:
button.setOnAction(event -> System.out.println(event));
可以簡化為:
button.setOnAction(System.out::println);
其中的System.out::println就是一個方法引用,需要注意的是,方法引用等同于一個lambda表達式,也是需要可以被轉換為一個對應的函數式接口。再舉一個例子,不區分大小寫對字符串進行排序:
Arrays.sort(strings, String::compareToIgnoreCase);
類名::靜態方法名,對靜態方法的引用;
類名::成員方法名,對第一個參數指定對象的成員方法的引用;
對象::成員方法名,對指定對象成員方法的引用;
示例分別如下:
示例1:(double x, double n) -> Math::pow;
示例2:Arrays.sort(strings, String::compareToIgnoreCase);
示例3:button.setOnAction(System.out::println);
其他常用方式示例:
this::實例方法;
super::實例方法。
格式: 類名::new ,示例:
Button::new, int[]::new(等價于x -> new int[x])
如果有多個構造器,編譯器會從中推斷并挑選一個最合適的構造器。
構造器引用可用于突破Java無法構建泛型數組的限制:
List<String> lables = ...; Stream<Button> stream = lables.stream().map(Button::new); Button[] buttons = stream.toArray(Button[]::new);
public static void repeatMessage(String text, int count) { Runnable r = () -> { for (int i=0; i < count; i++) { System.out.println(text); Thread.yield(); } } } new Thread(r).start();
一個lambda表達式有3個部分:
一段代碼;
參數;
自由變量的值,即不是參數又沒有在代碼中定義的變量的值,例如上例中的:text、count;
因為lambda表達式可能會再repeatMessage方法返回后執行,所以需要在方法被調用時就捕獲自由變量的值并保存起來,以便在表達式執行時使用變量值;
含有自由變量的代碼塊被稱為“閉包”,所以lambda表達式就是Java的閉包,內部類也是閉包;
在lambda表達式中,引用的外部變量值是不可以在表達式中被修改的,因為修改的話線程不安全,但是,此不可變的約束只做用在變量引用上,無法限制變量內部的值的修改,例如:數組元素、集合元素、或者其他實例變量的屬性等;
lambda表達式中使用this,引用的是創建該lambda表達式的方法所在對象,而非lambda表達式對應函數式接口實現類的this;
lambda表達式中不允許出現與局部變量同名的變量定義;
為了使存量接口能夠支持lambda表達式,同時又不影響已有的實現類,Java8開始支持接口的默認方法實現,這樣存量接口就可以通過添加默認方法的方式來支持lambda表達式。
選擇父類中的方法。如果一個父類中提供了具體的實現方法,那么接口中的默認同簽名方法會被忽略;
接口沖突。如果一個類的一個父接口提供了一個默認方法,另一個接口中有相同簽名的方法(不管是否默認方法),實現類必須覆蓋該方法來解決沖突。
感謝各位的閱讀,以上就是“Java8中lambda表達式的用法”的內容了,經過本文的學習后,相信大家對Java8中lambda表達式的用法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。