[Java] 17.3. 函式介面 & 預設方法

當一個介面要做為lambda的函式介面時,這時只能有一個未實作的方法,其他的必須使用default預設函式執行的內容。

 

image/svg+xml17.3. 函式介⾯與 default - function interface & default Employee e1 = new Employee( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); Employee e3 = new Employee( "K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); Employee e4 = new Employee( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); List < Employee > l = new ArrayList < Employee >(); l.add ( e1 ); l.add ( e2 ); l.add ( e3 ); l.add ( e4 ); List < Employee > result1 = Collection.filter ( l , emp -> emp.age >= 20 ); public interface Filter < T >{ boolean keep ( T item ); } import java.util.*; public class Collection { public static <T> List < T > filter ( List < T > list , Filter < T > filter ){ ArrayList < T > result = new ArrayList < T >(); for ( T item : list){ if ( filter.keep ( item ) == true ){ result.add(item) ; } } return result ; } } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); Employee e3 = new Employee( "K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); Employee e4 = new Employee( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); List < Employee > l = new ArrayList < Employee >(); l.add ( e1 ); l.add ( e2 ); l.add ( e3 ); l.add ( e4 ); List < Employee > result1 = Collection.filter ( l , emp -> emp.age >= 20 ); for ( Employee emp : result1){ System.out.println(emp.age); } List < Employee > result2 = Collection.filter ( l , emp -> emp.name == "Jack" || emp.name == "Mary" ); for ( Employee emp : result2){ System.out.println(emp.name); } } } public interface Filter < T >{ boolean keep ( T item); boolean drop ( T item); } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); Employee e3 = new Employee( "K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); Employee e4 = new Employee( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); List < Employee > l = new ArrayList < Employee >(); l.add(e1); l.add(e2); l.add(e3); l.add(e4); List < Employee > result1 = Collection.filter(l, emp -> emp.age >= 20 ); for ( Employee emp : result1){ System.out.println(emp.age); } } } 編譯失敗 Main.java:20: error: method filter in class Collection cannot be applied to given types; List<Employee> result1 = Collection.filter(l, emp - > emp.age >= 20); ^ required: List<T>,Filter<T> found: List<Employee>,(emp)->emp[...]>= 20 reason: cannot infer type-variable(s) T (argument mismatch; Filter is not a functional interface multiple non-overriding abstract methods found in interface Filter) where T is a type-variable: T extends Object declared in method <T>filter(List<T>,Filter<T>) 1 error import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); Employee e3 = new Employee( "K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); Employee e4 = new Employee( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); List < Employee > l = new ArrayList < Employee >(); l.add(e1); l.add(e2); l.add(e3); l.add(e4); final int baseAge = 20 ; List < Employee > result1 = Collection.filter(l, emp -> emp.age >= baseAge + 1 ); for ( Employee emp : result1){ System.out.println(emp.age); } int baseAge2 = 20 ; List < Employee > result2 = Collection.filter(l, emp -> { baseAge2 = baseAge2 + 1 ; return emp.age >= baseAge2; } ); for ( Employee emp : result2){ System.out.println(emp.age); } } } 編譯失敗 Main.java:36: error: local variables referenced from a lambda expression must be final or effectively final baseAge2 = baseAge2 + 1; ^ Main.java:36: error: local variables referenced from a lambda expression must be final or effectively final baseAge2 = baseAge2 + 1; ^ Main.java:37: error: local variables referenced from a lambda expression must be final or effectively final return emp.age >= baseAge2; ^ 3 errors public interface Filter < T >{ boolean keep ( T item); boolean drop ( T item); } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); Employee e3 = new Employee( "K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); Employee e4 = new Employee( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); List < Employee > l = new ArrayList < Employee >(); l.add(e1); l.add(e2); l.add(e3); l.add(e4); List < Employee > result1 = Collection.filter(l, emp -> emp.age >= 20 ); for ( Employee emp : result1){ System.out.println(emp.age); } } } 編譯失敗 Main.java:20: error: method filter in class Collection cannot be applied to given types; List<Employee> result1 = Collection.filter(l, emp - > emp.age >= 20); ^ required: List<T>,Filter<T> found: List<Employee>,(emp)->emp[...]>= 20 reason: cannot infer type-variable(s) T (argument mismatch; Filter is not a functional interface multiple non-overriding abstract methods found in interface Filter) where T is a type-variable: T extends Object declared in method <T>filter(List<T>,Filter<T>) 1 error public interface Filter < T >{ boolean keep ( T item); default boolean drop ( T item) { return !keep(item) ; } } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); Employee e3 = new Employee( "K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); Employee e4 = new Employee( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); List < Employee > l = new ArrayList < Employee >(); l.add(e1); l.add(e2); l.add(e3); l.add(e4); List < Employee > result1 = Collection.filter(l, emp -> emp.age >= 20 ); for ( Employee emp : result1){ System.out.println(emp.age); } } } public interface Filter < T >{ static boolean keep ( T item); } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 ); Employee e3 = new Employee( "K11111111" , "Mary" , 18 , " 女⽣ " , "050021" , 30000 ); Employee e4 = new Employee( "K22222222" , "Jack" , 19 , " 男⽣ " , "051212" , 42000 ); List < Employee > l = new ArrayList < Employee >(); l.add(e1); l.add(e2); l.add(e3); l.add(e4); List < Employee > result1 = Collection.filter(l, emp -> emp.age >= 20 ); } } 編譯失敗 Main.java:20: error: method filter in class Collection cannot be applied to given types; List<Employee> result1 = Collection.filter(l, emp - > emp.age >= 20); ^ required: List<T>,Filter<T> found: List<Employee>,(emp)->emp[...]>= 20 reason: cannot infer type-variable(s) T (argument mismatch; Filter is not a functional interface no abstract method found in interface Filter) where T is a type-variable: T extends Object declared in method <T>filter(List<T>,Filter<T>) ./Collection.java:15: error: illegal static interface method call if(filter.keep(item) == true){ ^ the receiver expression should be replaced with the type qualifier 'Filter<T>' where T is a type-variable: T extends Object declared in method <T>filter(List<T>,Filter<T>) ./Filter.java:9: error: missing method body, or declare abstract static boolean keep(T item); ^ 4 errors J17_3_1 Filter.java 1. 定義⼀過瀘的函式介⾯ - FIlter ,其⽀援泛型,為何稱為函式 介⾯ ? 因為 Java 這⼀類會給 lambda 使⽤的介⾯稱之為函式介⾯。 1. 在此使⽤泛型的 List ,指定放入的物件為員⼯ Employee 型別的物件。 2. 若想要開發⼀個 Collection 類別,然後有個 filter() ⽅法,可以 lambda 過瀘 l 變數中的 List<Employee> 員⼯,要怎麼做呢 ? 2. 其中有個 keep() ⽅法,帶入⼀個 T 型的物件,並回傳⼀個布林值表⽰是否這個 物件要保留,過瀘器會在為 true 時保留物件、 false 時略過此物件。 函式介⾯不⼀定要有泛型。 J17_3_1 Collection.java 1. 製作⼀個集合 Collection 類別。 2. 過瀘 filter ⽅法,會將第 1 個參數 帶入的 List 透過第 2 個參數過盧函式介 Filter 物件過瀘物件。 3. 注意,這個⽅法使⽤了雙箭頭 (<>) 定義了⼀個泛型 T ,回傳型 別、參數皆使⽤了這個泛型 T 4. 依序對每個 list 中的物件進⾏ keep() 測試,若為 true 則加入⾄ result 變數中的 ArrayList 物件中。 5. 最後回傳這個過瀘後的 ArrayList 物件。 J17_3_1