Java之函数式接口@FunctionalInterface详解

函数式接口的定义

在java8中,满足下面任意一个条件的接口都是函数式接口:

1、被@FunctionalInterface注释的接口,满足@FunctionalInterface注释的约束。

2、没有被@FunctionalInterface注释的接口,但是满足@FunctionalInterface注释的约束

@FunctionalInterface注释的约束:

1、接口有且只能有个一个抽象方法,只有方法定义,没有方法体

2、在接口中覆写Object类中的public方法,不算是函数式接口的方法。

比如:

@FunctionalInterface
interface FunctionalInterfaceTest {
String getInfo(String input);
}

函数式接口的实例

  1. lambda表达式
  2. 方法的引用
  3. 已有构造器或方法的引用
public class Main {

    public static void main(String[] args)
throws ClassNotFoundException,
IllegalAccessException,
InstantiationException,
NoSuchMethodException,
InvocationTargetException, NoSuchFieldException {
/**
* 1、lambda表达式
* 这种形式最为直观,lambda表达式,接收一个String类型的参数,返回一个String类型的结果。
* 完全符合函数式接口FunctionInterfaceTest的定义
*/
FunctionalInterfaceTest fiTest1 = str -> str + " copy";
/**
* 2、Main方法当中的functionalInterfaceTestMethod方法接收一个参数,返回一个结果。符合函数式接口
* FunctionInterfaceTest的定义。
* 函数式接口只是定义了个方法的约定(接收一个String类型的参数,返回一个String类型的结果),
* 而对于方法内部进行何种操作则并没有做任何的限制。在这点上,跟java以前的版本中的实现类与接口之间的
* 关系很类似。不同的是,函数式接口更偏重于计算过程,约束了一个计算过程的输入和输出。
*/
FunctionalInterfaceTest fiTest2 = Main::functionalInterfaceTestMethod;
/**
* 3、构造方法引用
* 构造函数的结构:接收输入参数,然后返回一个对象。这种约束跟函数式接口的约束很像。
* 所以只要“输入参数类型”与“输出参数类型”跟FunctionInterfaceTest中的方法约束相同,
* 就可以创建出FunctionInterfaceTest接口的实例,如下,String的构造方法中有
* new String(str)的构造方法,所以可以得到实例。
* 这里存在一个类型推断的问题,JDK的编译器已经帮我们自动找到了只有一个参数,且是String类型的构造方法。
* 这就是我们直接String::new,没有指定使用哪一个构造方法,却可以创建实例的原因
*/
FunctionalInterfaceTest fiTest3 = String::new; System.out.println(useFunctionalInterface("Hello World!", fiTest1));
System.out.println(useFunctionalInterface("Hello World!", fiTest2));
System.out.println(useFunctionalInterface("Hello World!", fiTest3));
System.out.println(useFunctionalInterface("Hello World!", str -> str + " created by lambda in the context"));
/**
输出:
Hello World! copy
Hello World! copy 2 by reference
Hello World!
Hello World! created by lambda in the context
*/
} public static String functionalInterfaceTestMethod(String str) {
return str + " copy 2 by reference";
} public static String useFunctionalInterface(String str, FunctionalInterfaceTest fiT) {
return fiT.getInfo(str);
}
}

常用的封装好的函数式接口

分别为Function<T, R>, Cosumer<T>, Predicate<T>, Supplier<T>

/**
* 常用的函数式接口主要有四种类型,是通过其输入和输出的参数来进行区分的。定义了编码过程中主要的使用场景。
Function<T,R>
接收一个T类型的参数,返回一个R类型的结果 Consumer<T>
接收一个T类型的参数,不返回值 Predicate<T>
接收一个T类型的参数,返回一个boolean类型的结果 Supplier<T>
不接受参数,返回一个T类型的结果
*/
Function<String, String> add_postfix = str -> str + "postfix";
Consumer<String> print_string = System.out::println;
Predicate<Integer> judge_positive = n -> n > 0;
Supplier<String> supplier = () -> "supply";
List<String> list = Arrays.asList("adfsg", "sdafef", "", "s", "231243", "hgjrepjrg");
list.stream()
.map(str -> str + "1")
.filter(str -> str.length() > 2)
.sorted((str1, str2) -> str2.compareTo(str1))
.forEach(System.out::println);
/**
输出:
sdafef1
hgjrepjrg1
adfsg1
2312431
1234dfgh
*/

此外,对于多参数的情况,Java还封装了BiFunction<T, U, R>, BiConsumer<T, U>, BiPredicate<T, U>。

// 由于java不能返回多个参数,所以没有BiSupplier
BiFunction<String, String, String> combine_string = (str1, str2) -> str1 + str2;
BiConsumer<String, String> print_two_string = (str1, str2) -> System.out.println(str1 + str2);
BiPredicate<String, String> str_equal = String::equals;
int bif_result = biFunctionTestMethod("abs", "pdf", (str1, str2) -> str1.length() + str2.length());
biConsumerTestMethod("1234", "dfgh", (str1, str2) -> System.out.println(str1 + str2));
boolean bip_result_1 = biPredictTestMethod("abc", "abc", str_equal),
bip_result_2 = biPredictTestMethod("abc", "def", str_equal);
System.out.println(bif_result);
System.out.println(bip_result_1);
System.out.println(bip_result_2);
/*
输出:
6
true
false
*/

在此之外,还有compose和andThen方法,其本质就是数学当中的符合函数,唯一的区别:对于函数\(f(x),g(x)\),compose等价于\(f(g(x))\),andThen等价于\(g(f(x))\),就是执行顺序不同而已。

// compose 和 andThen
Function<String, String> compose_function = ((Function<String, String>) (str -> str + "abc")).compose((Function<String, String>) (str -> str + str.length()));
System.out.println("Compose function: " + compose_function.apply("Hello World! "));
Function<String, String> andThen_function = ((Function<String, String>) (str -> str + "abc")).andThen((Function<String, String>) (str -> str + str.length()));
System.out.println("AndThen function: " + andThen_function.apply("Hello World! "));
// Bicosumer, cosumer, bifunction 都有类似功能 // BiPredicate, Predicate 的 and, or, negate
System.out.println(str_equal.negate().test("a", "a")); // false
System.out.println(judge_positive.and(n -> n > 2).test(5)); // true
System.out.println(judge_positive.or(n -> n < -1).test(-10)); // true

源码

Function.java

/**
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> { /**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t); /**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
} /**
* Returns a composed function that first applies this function to
* its input, and then applies the {@code after} function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*
* @see #compose(Function)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
} /**
* Returns a function that always returns its input argument.
*
* @param <T> the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}

Consumer.java

/**
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> { /**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t); /**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}

Predicate.java

/**
* Represents a predicate (boolean-valued function) of one argument.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #test(Object)}.
*
* @param <T> the type of the input to the predicate
*
* @since 1.8
*/
@FunctionalInterface
public interface Predicate<T> { /**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t); /**
* Returns a composed predicate that represents a short-circuiting logical
* AND of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code false}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ANDed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* AND of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
} /**
* Returns a predicate that represents the logical negation of this
* predicate.
*
* @return a predicate that represents the logical negation of this
* predicate
*/
default Predicate<T> negate() {
return (t) -> !test(t);
} /**
* Returns a composed predicate that represents a short-circuiting logical
* OR of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code true}, then the {@code other}
* predicate is not evaluated.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ORed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* OR of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
} /**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
} /**
* Returns a predicate that is the negation of the supplied predicate.
* This is accomplished by returning result of the calling
* {@code target.negate()}.
*
* @param <T> the type of arguments to the specified predicate
* @param target predicate to negate
*
* @return a predicate that negates the results of the supplied
* predicate
*
* @throws NullPointerException if target is null
*
* @since 11
*/
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}

Supplier.java

/**
* Represents a supplier of results.
*
* <p>There is no requirement that a new or distinct result be returned each
* time the supplier is invoked.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #get()}.
*
* @param <T> the type of results supplied by this supplier
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> { /**
* Gets a result.
*
* @return a result
*/
T get();
}

Java之函数式接口@FunctionalInterface详解(附源码)的更多相关文章

  1. struts2内置拦截器和自定义拦截器详解(附源码)

    一.Struts2内置拦截器 Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特 性.这些内置的拦截器在struts-default.xml中配置.只有配置了拦截 ...

  2. 转载—— android 瀑布流的实现详解,附源码

    介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https:/ ...

  3. C# Socket-TCP异步编程原理详解附源码

    目录 目录异步原理主要方法源码Server源码:Client源码实验效果(广播为例)参考博客 TOC 异步原理 套接字编程原理:延续文件作用思想,打开-读写-关闭的模式. C/S编程模式如下: Ø 服 ...

  4. Java SPI机制实战详解及源码分析

    背景介绍 提起SPI机制,可能很多人不太熟悉,它是由JDK直接提供的,全称为:Service Provider Interface.而在平时的使用过程中也很少遇到,但如果你阅读一些框架的源码时,会发现 ...

  5. Android应用AsyncTask处理机制详解及源码分析

    1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个知识点.前面我们分析了Handler异步机制原理(不了解的可以阅读我的<Android异步消息处理机 ...

  6. Spring Boot启动命令参数详解及源码分析

    使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...

  7. 【转载】Android应用AsyncTask处理机制详解及源码分析

    [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个 ...

  8. 详解ConCurrentHashMap源码(jdk1.8)

    ConCurrentHashMap是一个支持高并发集合,常用的集合之一,在jdk1.8中ConCurrentHashMap的结构和操作和HashMap都很类似: 数据结构基于数组+链表/红黑树. ge ...

  9. 线程池底层原理详解与源码分析(补充部分---ScheduledThreadPoolExecutor类分析)

    [1]前言 本篇幅是对 线程池底层原理详解与源码分析  的补充,默认你已经看完了上一篇对ThreadPoolExecutor类有了足够的了解. [2]ScheduledThreadPoolExecut ...

随机推荐

  1. codeforces 1183F 离散化枚举 约数定理

    codeforces1183F 有技巧的暴力 传送门:https://codeforces.com/contest/1183/problem/F 题意: 给你n个数,要你从中选出最多三个数,使得三个数 ...

  2. Qt、Vc下用fopen打开中文名字的文件(转换成Unicode后,使用_wfopen函数)

    在做一个Qt项目的时候,完成上传文件时,通过fopen打开文件用来读时发现fopen不能打开中文的文件名,自己在网查找一下,解决方法如下 参考:http://weidaohang.org/wanglu ...

  3. 【Linux】Linux下date,time等时间设置

    date命令的帮助信息 [root@localhost source]# date --help用法:date [选项]... [+格式] 或:date [-u|--utc|--universal] ...

  4. 第二阶段:流程图:8.axure绘制简单业务流程图

    元件库选择流程图 流程图示例 一个简单的注册练习 线上可以写字 作业

  5. 优雅的使用BeanUtils对List集合的操作

    摘要 在业务员流程的时候,我们在Entity.Bo.Vo层数据间可能经常转换数据,Entity对应的是持久层数据结构(一般是数据库表的映射模型).Bo对应的是业务层操作的数据结构.Vo就是Contro ...

  6. Java动态代理 ----- jdk代理与cglib代理

    1.jdk代理 针对接口进行代理,接口可以没有方法, InvocationHandler会拦截所有方法,不过好像意义不大....只能执行Object类的方法,执行结果有点奇怪... package t ...

  7. 数据导出至excle

    ASP.NET MVC导出Excel 首先下载  NPOI.dll 引用到项目中 建议下载地址:http://download.csdn.net/detail/pukuimin1226/5851747 ...

  8. cmake安装mysql及多实例配置方法

    一.安装mysql 1. 生产环境如何选择MySQL版本 1. 选择社区版的稳定GA版本2. 可以选择5.1或5.5.互联网公司主流5.5, 其次是5.1和5.63. 选择发布后6个月以上的GA版4. ...

  9. 关于SAM和广义SAM

    关于SAM和广义SAM 不是教程 某些思考先记下来 SAM 终于学会了这个东西诶...... 一部分重要性质 确定一个重要事情,S构造出的SAM的一个重要性质是当且仅当对于S的任意一个后缀,可以从1号 ...

  10. Appium Mac系统 自动测试环境搭建

    一.python 环境准备 Mac 自带 Python 环境,一般为 2.7 版本. 1.查看当前系统默认的Python路径 which python ==> /usr/bin/python 2 ...