/**
* An informative annotation type used to indicate that an interface
* type declaration is intended to be a <i>functional interface</i> as
* defined by the Java Language Specification.
*
* Conceptually, a functional interface has exactly one abstract
* method. Since {@linkplain java.lang.reflect.Method#isDefault()
* default methods} have an implementation, they are not abstract. If
* an interface declares an abstract method overriding one of the
* public methods of {@code java.lang.Object}, that also does
* <em>not</em> count toward the interface's abstract method count
* since any implementation of the interface will have an
* implementation from {@code java.lang.Object} or elsewhere.
*
* <p>Note that instances of functional interfaces can be created with
* lambda expressions, method references, or constructor references.
*
* <p>If a type is annotated with this annotation type, compilers are
* required to generate an error message unless:
*
* <ul>
* <li> The type is an interface type and not an annotation type, enum, or class.
* <li> The annotated type satisfies the requirements of a functional interface.
* </ul>
*
* <p>However, the compiler will treat any interface meeting the
* definition of a functional interface as a functional interface
* regardless of whether or not a {@code FunctionalInterface}
* annotation is present on the interface declaration.
*
* @jls 4.3.2. The Class Object
* @jls 9.8 Functional Interfaces
* @jls 9.4.3 Interface Method Body
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
从注释我们可以得出
下面自定义一个自己的函数式接口 :
@FunctionalInterface
public interface MyFunction {
//只能有一个抽象方法
public void handlerMyFunction();
//接口默认方法 jdk1.8 新提供default特性
default void handlerFunction() {
System.out.println("this is my interface method");
}
//静态方法
static void getFunction() {
System.out.println("this is static method");
}
}
default 是 jdk1.8提出的,思考一下为什么会提供这个功能?
在List接口中,我们可以看到如下方法。
default void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final ListIterator<E> li = this.listIterator(); while (li.hasNext()) { li.set(operator.apply(li.next())); } } default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } }
你会神奇的发现,List 从jdk1.2版本开始,使用了这么时间的接口,竟然能够通过default方法进行扩展接口的功能。
通过函数式接口接口的简单理解,那我们看下jdk1.8为我们提供了哪些接口
函数式接口 | 参数类型 | 返回参数 | 使用场景 |
---|---|---|---|
Consumer 消费型接口 | T | void | 对类型为 T 的对象应用操作,接口定义的方法:void accept(T t) |
Supplier 供给型接口 | 无 | T | 返回类型为 T 的对象,接口定义的方法:T get() |
Function<T, R>函数式接口 | T | R | 对类型为 T 的对象应用操作,并 R 类型的返回结果。接口定义的方法:R apply(T t) |
Predicate 断言型接口 | T | boolean | 确定类型为 T 的对象是否满足约束条件,并返回boolean 类型的数据 接口定义的方法:boolean test(T t) |
Consumer 接口是消费性接口,无返回值
public class ConsumerFunction {
public static void main(String[] args) {
handlerConsumer(1000, (integer) -> {
for (int i = 0; i < integer; i++) {
System.out.println("number: " + i);
}
});
}
public static void handlerConsumer(Integer number, Consumer<Integer> consumer) {
consumer.accept(number);
}
}
Supplier 接口是供给型接口,有返回值
public class SupplierFunction {
public static void main(String[] args) {
List<Integer> numberList = getNumberList(10, () -> new Random().nextInt(100));
System.out.println(numberList);
}
public static List<Integer> getNumberList(int num, Supplier<Integer> supplier) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
list.add(supplier.get());
}
return list;
}
}
Function 接口是函数型接口,有返回值
public class FunctionFunction {
public static void main(String[] args) {
String hello = handlerString("hello", s -> s.toUpperCase());
System.out.println(hello);
}
public static String handlerString(String str, Function<String, String> function) {
return function.apply(str);
}
}
Predicate 接口是断言型接口,返回值类型为 boolean
public class PredicateFunction {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("hello", "World", "Lambda", "Predicate");
List<String> strings = filterString(stringList, str -> str.length() > 5);
System.out.println(strings);
}
public static List<String> filterString(List<String> list, Predicate<String> predicate) {
List<String> result = new ArrayList<>();
for (String str : list) {
if (predicate.test(str)) {
result.add(str);
}
}
return result;
}
}
通过上面的事例,我的理解函数式接口似乎和匿名内部类,和lambda表达式是一个东西。如果更清晰概括的读者,可以在评论区留下你的理解和概括。
函数式接口 | 参数类型 | 返回参数 | 使用场景 |
---|---|---|---|
BiFunction(T, U, R) | T, U | R | 对类型为 T,U 的参数应用操作,返回 R 类型的结果。接口定义的方法:R apply(T t, U u) |
UnaryOperator | T | T | 对类型为 T 的对象进行一 元运算, 并返回 T 类型的 结果。 包含方法为 T apply(T t) |
BinaryOperator | T, T | T | 对类型为 T 的对象进行二 元运算, 并返回 T 类型的 结果。 包含方法为T apply(T t1, T t2) |
BiConsumer<T, U> | T, U | void | 对类型为 T, U 参数应用 操作。 包含方法为 void accept(T t, U u) |
ToIntFunction | T | int | 计算 int 值的函数 |
ToLongFunction | T | long | 计算 long 值的函数 |
ToDoubleFunction | T | double | 计算 double 值的函数 |
IntFunction | int | R | 参数为 int 类型的函数 |
LongFunction | long | R | 参数为 long 类型的函数 |
DoubleFunction | double | R | 参数为 double 类型的函数 |
? 通过使用函数式接口,可以将Lambda表达式作为参数传递给方法,从而简化代码,提高代码的可读性和维护性,当然这种简洁性和可读性是仁者见仁,智者见智的事情。