什么是函數編程接口?
約束:抽象方法有且只有一個,即不能有多個抽象方法,在接口中覆寫Object類中的public方法(如equals),不算是函數式接口的方法。
被@FunctionalInterface注解該接口,沒有該注解的接口滿足約束也行。
在Java8中,滿足下面任意一個條件的接口都是函數式接口:
- 被@FunctionalInterface注釋的接口,滿足函數式接口的約束。
- 沒有被@FunctionalInterface注釋的接口,但是滿足函數式接口的約束。
- @函數式的約束:
- 接口有且只能有個一個抽象方法,只有方法定義,沒有方法體。
- 在接口中覆寫Object類中的public方法,不算是函數式接口的方法。
- 在接口中的default方法,不算是函數式接口的方法。
- 在接口中的static方法,不算是函數式接口的方法。
自定義一個函數式編程接口
/** * 自定義一個函數式編程接口 * 函數式編程只有一個抽象方法,所以默認的是實現的是這個抽象方法 * @param <T> * @param <R> */ @FunctionalInterface public interface CalcFunctionInterface<T, R> { /** * 計算t1和t2 * * @param t1 * @param t2 * @return */ R calc(T t1, T t2); }
傳入不同calc函數實現的對象,進行調用
相當於以前創建CalcFunctionInterface的匿名類,重寫了calc方法(由於只有一個抽象方法,所以默認就是calc方法)
/** * 相當於一個類實現了CalcFunction接口中的唯一一個函數calc * 然后在利用多態,調用calc函數,傳入兩個參數,進行計算 */ @Test public void add(){ CalcFunctionInterface<Integer, Integer> add = (t1, t2) -> t1+t2; Integer calc = add.calc(2, 3); System.out.println(calc); // 5 }
傳入一個匿名類對象,進行方法調用calc
@Test public void multiply(){ // 相當於通過匿名類的形式傳入一個實現了CalcFunctionInterface接口的子類對象,重寫了該接口的方法 Integer calc = FunctionalInterfacesTest.calc(2, 3, (t1, t2) -> t1 * t2); System.out.println(calc); // 6 } /** * 接受了一個對象,利用對象的calc方法計算 */ public static Integer calc(Integer i1, Integer i2, CalcFunctionInterface<Integer, Integer> calc){ return calc.calc(i1,i2); }
便捷的引用類的構造器及方法
一個Convert接口
@FunctionalInterface public interface Convert<F, T> { T convert(F from); }
lambda表達式的形式重寫該函數式編程的唯一接口
@Test public void testLambda(){ Convert<String, Integer> stringIntegerConvert = (from -> Integer.valueOf(from)); Integer convert = stringIntegerConvert.convert("123"); System.out.println(convert); // 123 }
下面使用"::"運算符更精簡
靜態方法
@Test public void testStaticMethod(){ Convert<String, Instant> stringInstantConvert = Instant::parse; Instant convert = stringInstantConvert.convert("2019-04-25T16:09:03.852Z"); System.out.println(convert); // 2019-04-25T16:09:03.852Z }
實例方法
/** * 實例對象的方法 */ @Test public void testObjectMethod(){ Something something = new Something(); Convert<String, String> startsWith = something::startsWith; String convert = startsWith.convert("123"); System.out.println(convert); // 1 }
class Something { public String startsWith(String s) { return String.valueOf(s.charAt(0)); } }
對象的構造方法
/** * 調用對象的構造方法 */ @Test public void testConstructor(){ PersonFactory<Person> personFactory = Person::new; Person person = personFactory.create("Chris", "Paul"); System.out.println(person); // Person(firstName=Chris, lastName=Paul) }
/** * Person 工廠 */ @FunctionalInterface public interface PersonFactory<P extends Person> { P create(String firstName, String lastName); }
@NoArgsConstructor @AllArgsConstructor @Getter @Setter @ToString class Person { private String firstName; private String lastName; }
Java8的內置函數式編程接口
https://juejin.im/post/5c7d1254e51d45720f72264c