Java Review (十六、面向對象----Lambda 表達式)
文章目錄
Lambda表達式入門
用匿名內部類實現命令模式
Lambda表示式實現命令模式
Lambda 表達式與函數式接口
方法引用與構造器引用
引用類方法
引用特定對象的實例方法
引用某類對象的實例方法
引用構造器
Lambda 表達式與匿名內部類的聯系和區別
Lambda表達式入門
用匿名內部類實現命令模式
public interface Command { //接口里定義的方法相當于處理封裝行為 int progress(int[] target); }
1
2
3
4
public class ProgressArray { public ProgressArray() { } public void progress(int[] target,Command cmd) { cmd.progress(target); } }
1
2
3
4
5
6
7
8
public class CommandInnerTest { public CommandInnerTest() { } public static void main(String[] args) { ProgressArray progressArray=new ProgressArray(); int[] array= new int[] {3, -4, 6, 4} ; //處理數組,具體處理行為取決于匿名內部類 progressArray.progress(array, new Command() { @Override public void progress(int[] target) { int sum=0; int[] a=target; for(int j=0;j 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Lambda表示式實現命令模式 Lambda 表達式可用于簡化創建匿名內部類對象: public class CommandLambdaTest { public static void main(String[] args) { ProgressArray progressArray = new ProgressArray(); int[] array = { 3, -4, 6, 4 }; // 處理數組,具體行為取決于匿名內部類 progressArray.progress(array, (int[] target) -> { int sum = 0; for (int temp : array) { sum += temp; } System.out.println("數組元素總和為" + sum); }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 當使用 Lambda 表達式代替匿名內部類創建對象時, Lambda 表達式的代碼 塊將會代替實現抽象方法的方法體, Lambda 表達式就相當一個匿名方法。 從上面語法格式可以看出, Lambda 表達式的主要作用就是代替匿名內部類的煩瑣語法。它分三部分組成。 形參列表 。形參列表允許省略形參類型 。如果形參列表中只有一個參數,甚至連形參列表的圓括號也可以省略。 箭頭 —>。必須通過英文中畫線和大于符號組成。 代碼塊。如果代碼塊只包含一條語句, Lambda 表達式允許省略代碼塊的花括號,那么這條語句就不要用花括號表示語句結束。 Lambda 碼塊只有一條 return語句,甚至可以省略return關鍵字, Lambda 表達式會自動返回這條語句的值。 public class LambdaTest { public static void main(String[] args) { LambdaTest tester=new LambdaTest(); // 類型聲明 MathOperation addition = (int a, int b) -> a + b; // 不用類型聲明 MathOperation subtraction = (a, b) -> a - b; // 大括號中的返回語句 MathOperation multiplication = (int a, int b) -> { return a * b; }; // 沒有大括號及返回語句 MathOperation division = (int a, int b) -> a / b; System.out.println("10 + 5 = " + tester.operate(10, 5, addition)); System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + tester.operate(10, 5, division)); // 不用括號 GreetingService greetService1 = message -> System.out.println("Hello " + message); // 用括號 GreetingService greetService2 = (message) -> System.out.println("Hello " + message); greetService1.sayMessage("Runoob"); greetService2.sayMessage("Google"); } interface MathOperation { int operation(int a, int b); } interface GreetingService { void sayMessage(String message); } private int operate(int a, int b, MathOperation mathOperation) { return mathOperation.operation(a, b); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 Lambda 表達式與函數式接口 Lambda 表達式的類型,也被稱為"目標類型( target type) ", Lambda 表達式的目標類型必須是"函數式接口( functional interface ) "。 函數式接口代表只包含一個抽象方法的接口 。 函數式接口可以包含多個默認方法、類方法,但只能聲明一個抽象方法 。 如果采用匿名內部類語法來創建函數式接口的實例,則只需要實現一個抽象方法,在這種情況下即可采用 Lambda 表達式來創建對象,該表達式創建出來的對象的目標類型就是這個函數式接口 。 查詢 Java 8的 API 文檔,可以發現大量的函數式接口,例如: Runnable、 ActionListener 等接口都是函數式接口 。 Java 8專門為函數式接口提供了 @FunctionalInterface 注解,該注解通常放在接口定義前面,該注解對程序功能沒有任何作用,它用于告訴編譯器執行更嚴格檢查一一檢查該接口必須是函數式接口 ,否則編譯器就會報錯。 由于 Lambda 表達式的結果就是被當成對象 , 因此程序中完全可以使用 Lambda 表達式進行賦值, 例如如下代碼 : // Runnable 接口中只包含一個無參數的方法 // Lambda 表達式代表的匿名方法實現了 Runnable 接口中唯一的、無參數的方法 // 因此下面的 Lambda 表達式創建了 一個 Runnable 對象 Runnable r = () -> { for(int i = 0 ; i < 100 ; i ++){ System.out.println() ; } } 1 2 3 4 5 6 7 8 9 Lambda 表達式實現的是匿名方法,因此它只能實現特定函數式接口中的唯一方法 。 這意味著 Lambda 表達式有如下兩個限制 : Lambda 表達式的目標類型必須是明確的函數式接口 。 Lambda 表達式只能為函數式接口創建對象 。 Lambda 表達式只能實現一個方法 , 因此它只能為只有一個抽象方法的接口(函數式接口)創建對象 。 為了保證 Lambda 表達式的目標類型是一個明確的函數式接口,可以有如下三種常見方式 。 將 Lambda 表達式賦值給函數式接口類型的變量 。 將 Lambda 表達式作為函數式接口類型的參數傳給某個方法 。 使用函數式接口對 Lambda 表達式進行強制類型轉換。 Object obj1 = (Runnable) () - > { for(int i = 0 ; i < 100 ; i ++{ System.out.println(i); } 1 2 3 4 方法引用與構造器引用 如果 Lambda 表達式的代碼塊只有一條代碼,程序就可以省略Lambda 表達式中 代碼塊的花括號 。 不僅如此,如果 Lambda 表達式的代碼塊只有一條代碼,還可以在代碼塊中使用方法引用和構造器引用 。 方法引用和構造器引用可以讓 Lambda 表達式的代碼塊更加簡潔 。 方法引用和構造器引用都需要使用兩個英文冒號。 引用類方法 //函數式接口 @FunctionalInterface interface Converter{ //將 String 參數轉換為Integer Integer convert(String from); } 1 2 3 4 5 6 // 下面代碼使用 Larnbda 表達式創建 Converter 對象 Converter converterl = from -> Integer.valueOf(from); 1 2 //調用 converterl 對象的 convertO方法將字符串轉換為整數 Integer val = converterl.convert( " 99 " ); System.out.println (val); // 輸出整數 99 1 2 3 可以如下替換: //方法引用代替 Larnbda 表達式:引用類方法 //函數式接口中被實現方法的全部參數傳給該類方法作為參數 Converter converterl = Integer::valueOf; 1 2 3 引用特定對象的實例方法 // 下面代碼使用 Larnbda 表達式創建 Converter 對象 Converter converter2 = from - > " fkit.org ".indexOf (from) ; 1 2 //調用 converterl 對象的 convertO方法將字符串轉換為整數 Integer value = converter2.convert( "it "}; System.out.println(value} ; //輸出 2 1 2 3 可以如下替換: // 方法引用代替 Lambda 表達式 : 引用特定對象 的實例方法 // 函數式接口中被實現方法的全部參數傳給該方法作為參數 Converter converter2 = "fkit.org": :indexOf ; 1 2 3 引用某類對象的實例方法 //定義函數式接口 @Functionallnterface interface MyTest{ //根據 String 、 int 、 int 三個參數生成一個 String返回值 String test(String a , int b , int c); } 1 2 3 4 5 6 // 下面代碼使用 Lambda 表達式創建 MyTest 對象 MyTest mt = (a , b , c) - > a.substring(b , c}; 1 2 //調用mt的test()方法 String str = mt.test( "Java 1 Love you" , 2 , 9) ; System.out.println(str} ; // 輸出 : va 1 Lo 1 2 3 可以如下替換: // 方法引用代替 Lambda 表達式: 引 用某類對象 的實例方法 // 函數式接口中被實現方法的第一個參數作為調用者 // 后面的參數全部傳給該方法作為參數 MyTest mt = String ::substring; 1 2 3 4 引用構造器 @Funct ionallnterface interface YourTest{ //根據 String 參數生成一個 JFrame 返回值 JFrame win(String title); 1 2 3 4 // 下面代碼使用 Lambda 表達式創建 YourTest 對象 YourTest yt = (String a) - > new JFrame(a); 1 2 JFrame jf = yt.win( "我的窗口 ") ; System.out.println(jf) ; 1 2 可以如下替換: // 構造器引用代替 Lambda 表達式 //函數式接口中被實現方法的全部參數傳給該構造器作為參數 YourTest yt = JFrame ::new; 1 2 3 Lambda 表達式與匿名內部類的聯系和區別 從前面介紹可以看出, Lambda 表達式是匿名內部類的一種簡化 , 因此它可以部分取代匿名內部類的作用。 Lambda 表達式與匿名內部類存在如下相同點 : Lambda 表達式與匿名內部類一樣,都可以直接訪問 “effectively final” 的局部變量,以及外部類的成員變量(包括實例變量和類變量〉 。 Lambda 表達式創建的對象與匿名內部類生成的對象一樣,都可以直接調用從接口中繼承的默認方法 。 Lambda 表達式與匿名內部類主要存在如下區別: 匿名內部類可以為任意接口創建實例一一不管接口包含多少個抽象方法,只要匿名內部類實現所有的抽象方法即可;但 Lambda 表達式只能為函數式接口創建實例。 匿名內部類可以為抽象類甚至普通類創建實例 ; 但 Lambda 表達式只能為函數式接口創建實例 。 匿名內部類實現的抽象方法的方法體允許調用接口中定義的默認方法 ; 但 Lambda 表達式的代碼塊不允許調用接口中定義的默認方法。 參考: 【1】:《瘋狂Java講義》 【2】:https://www.jb51.net/article/171183.htm 【3】:https://www.runoob.com/java/java8-lambda-expressions.html 【4】:《Java核心技術 卷一》 Java 面向對象編程
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。