什么是函数编程接口?
约束:抽象方法有且只有一个,即不能有多个抽象方法,在接口中覆写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