函数式接口Function(二)
函数式接口Function(二)
1.函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
Functional Interface(功能接口)为lambda表达式和方法引用(用冒号::来进行方法的调用)提供目标类型。每个功能接口都有一个抽象方法,称为该功能接口的功能方法,lambda表达式的参数和返回类型与之匹配或适配。功能接口可以在多个上下文中提供目标类型,例如赋值上下文,方法调用或强制转换上下文:
// Assignment context Predicate<String> p = String::isEmpty; // Method invocation context stream.filter(e -> e.getSize() > 10)... // Cast context stream.map((ToIntFunction) e -> e.getSize())...
函数式接口可以使用lambda表达式,方法引用或构造函数引用创建功能接口的实例。
Java8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当接口不符合函数式接口定义的时候,编译器会报错。
此注解不是编译器将接口识别为功能接口的必要条件,而仅是帮助捕获设计意图并获得编译器帮助识别意外违反设计意图的帮助。
正确例子,没有报错:
@FunctionalInterface public interface HelloWorldService { void sayHello(String msg); }
错误例子,接口中包含了两个抽象方法,违反了函数式接口的定义,提示在接口中找到多个非重写的抽象方法
@FunctionalInterface public interface HelloWorldService { void sayHello(String msg); void sayWorld(String msg); }
注意: 加不加 @FunctionalInterface对于接口是不是函数式接口没有影响,该注解只是提醒编译器去检查该接口是否仅包含一个抽象方法
1.1允许定义默认方法
函数式接口里是可以包含默认方法,因为默认方法不是抽象方法,其有一个默认实现,所以是符合函数式接口的定义的。
如下代码不会报错:
@FunctionalInterface public interface HelloWorldService { void sayHello(String msg); default void doSomeWork1() { // Method body } default void doSomeWork2() { // Method body } }
1.2允许定义静态方法
函数式接口里是可以包含静态方法,因为静态方法不能是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义的。
如下代码不会报错:
@FunctionalInterface public interface HelloWorldService { void sayHello(String msg); static void printHello() { System.out.println("Hello"); } }
1.3允许定义java.lang.Object的public方法
函数式接口里是可以包含Object里的public方法,这些方法对于函数式接口来说,不被当成是抽象方法(虽然它们是抽象方法);因为任何一个函数式接口的实现,默认都继承了Object类,包含了来自java.lang.Object里对这些抽象方法的实现;
如下代码不会报错:
@FunctionalInterface public interface HelloWorldService { void sayHello(String msg); @Override boolean equals(Object obj); }
1.4已有函数式接口
函数式接口可以对现有的函数友好地支持lambda。
JDK1.8之前已有的函数式接口:
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
JDK1.8新增加的函数接口:
- java.util.function
2.Function函数
1 Function<T,R> 接收一个参数并返回结果的函数
2 BiFunction<T,U,R> 接受两个参数并返回结果的函数
3 DoubleFunction<R> 接收一个double类型的参数并返回结果的函数
4 DoubleToIntFunction 接收一个double类型的参数并返回int结果的函数
5 DoubleToLongFunction 接收一个double类型的参数并返回long结果的函数
6 IntFunction<R> 接收一个int类型的参数并返回结果的函数
7 IntToDoubleFunction 接收一个int类型的参数并返回double结果的函数
8 IntToLongFunction 接收一个int类型的参数并返回long结果的函数
9 LongFunction<R> 接收一个long类型的参数并返回结果的函数
10 LongToDoubleFunction 接收一个long类型的参数并返回double结果的函数
11 LongToIntFunction 接收一个long类型的参数并返回int结果的函数
12 ToDoubleBiFunction<T,U> 接收两个参数并返回double结果的函数
13 ToDoubleFunction<T> 接收一个参数并返回double结果的函数
14 ToIntBiFunction<T,U> 接收两个参数并返回int结果的函数
15 ToIntFunction<T> 接收一个参数并返回int结果的函数
16 ToLongBiFunction<T,U> 接收两个参数并返回long结果的函数
17 ToLongFunction<T> 接收一个参数并返回long结果的函数
2.1Function<T, R>
| 接口方法 | 方法描述 |
| R apply(T t) | 将此参数应用到函数中 |
| Function<T, R> andThen(Function<? super R,? extends V> after) | 返回一个组合函数,该函数结果应用到after函数中 |
| Function<T, R> compose(Function<? super V,? extends T> before) | 返回一个组合函数,首先将入参应用到before函数,再将before函数结果应用到该函数中 |
①apply(T t)
Function<String, String> function = a -> a + " Jack!"; System.out.println(function.apply("Hello")); // Hello Jack!
②andThen(Function<? super R,? extends V> after)
Function<String, String> function = a -> a + " Jack!"; Function<String, String> function1 = a -> a + " Bob!"; String greet = function.andThen(function1).apply("Hello"); System.out.println(greet); // Hello Jack! Bob!
③compose(Function<? super V,? extends T> before)
Function<String, String> function = a -> a + " Jack!"; Function<String, String> function1 = a -> a + " Bob!"; String greet = function.compose(function1).apply("Hello"); System.out.println(greet); // Hello Bob! Jack!
2.2BiFunction<T, U, R>
2.3DoubleFunction
2.4DoubleToIntFunction
2.5ToDoubleBiFunction<T,U>
2.6ToDoubleFunction
浙公网安备 33010602011771号