函数式接口(Functional Interface)是 Java 8对一类特殊类型的接口的称呼,这类接口只定义了唯一的抽象方法的接口, 因此也称为SAM接口,即Single Abstract Method interfaces。
@FunctionalInterface注解
新建一个接口
如果接口中没有方法,并且添加@FunctionalInterface注解。就会报错
当我们添加一个方法后。就正常了。
我们在新增一个方法。又报错了。这就很好解释了“接口只定义了唯一的抽象方法的接口”。
因为默认的static方法、equals等方法。不是抽象方法,其有一个默认实现,所以是符合函数式接口的定义的。
注意
1、该注解只能标记在"有且仅有一个抽象方法"的接口上。
2、JDK8接口中的静态方法和默认方法,都不算是抽象方法。
3、接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么 也不算抽象方法。
函数式接口类型
测试函数式接口
测试自定义接口
@Test
public void test() {
UserService userService = username -> new User(4, username, "30");
log.info("测试结果:{}", userService.getUserByUsername("Ross Zhang"));
UserService2 userService2 = username -> log.info("测试结果2:{}", username);
userService2.getUserByUsername("Ross Zhang");
UserExecutor userExecutor = new TestUserExecutor();
// UserExecutor userExecutor = UserService3::getUser;
userExecutor.execute(() -> {
log.info("测试userExecutor结果:{}", new User(4, "张三", "30"));
});
}
常用的函数式接口
Function:一个参数且有返回值
@Test
public void test4() {
/**
* Function<T, R> 一共有四个方法,接受一个T类型的参数,返回一个R类型的结果
* apply() 将此函数应用于给定参数,输入 T ,返回 R
* compose()
* andThen()
* identity() 始终返回其输入参数的函数。
*/
Function<User, String> functionUser = User::getUsername;
log.info("测试apply结果:{}", functionUser.apply(new User(1, "RossZhang", "19")));
// <V> Function<V, R> 方法名 Function<? super V, ? extends T>
// Function<String, User> before = ;
log.info("测试结果compose:{}", functionUser.compose(username -> new User(10, String.valueOf(username), "20")).apply("王麻子"));
log.info("测试结果andThen:{}", functionUser.andThen(item -> "三分归元气").apply(new User()));
Function<User, User> identity = Function.identity();
log.info("测试结果identity:{}", Function.identity().apply(new User()));
log.info("测试结果identity2:{}", identity.apply(new User(1, "张三丰", "120")));
}
Supplier:无参但有返回值
@FunctionalInterface
public interface UserService5<T> {
public T getUser();
}
// Supplier:无参但有返回值
@Test
public void test2() {
UserService5<User> service4 = () -> new User(1, "rosszhang", "20");
log.info("测试结果:{}", service4.getUser());
}
Consumer:一个参数但无返回值
@FunctionalInterface
public interface UserService4<T> {
public void getUser(T t);
}
@Test
public void test2() {
UserService4<User> service4 = item -> log.info("测试结果:{}", item);
service4.getUser(new User(1, "rosszhang", "20"));
}
Predicate:一个参数且返回boolean值
@FunctionalInterface
public interface UserService6<T> {
public boolean getUser(T t);
}
// Predicate:一个参数且返回boolean值
@Test
public void test4() {
UserService6<User> service4 = log -> log.equals(new User());
log.info("测试结果:{}", service4.getUser(new User()));
}
实际代码中的应用:
List<String> result = list
.stream()
// 这个地方用的是 Predicate<T>下的boolean test(T t);方法
.filter(e -> !e.startsWith("李"))
.collect(Collectors.toList());
// Supplier
Supplier<Integer> supplier =
() -> Integer.valueOf(BigDecimal.TEN.toString());
//Consumer<T>下的void accept(T t)方法
itemList.stream().forEach(item -> {
processCouponPrice(userId, item);
processDeliveryPrice(userId, item);
});
下图是JavaUtil中已经有的的方法。可以根据需要灵活引用,不需要我们在造轮子
Lambda表达式这种写法,感觉看着高大上。但是好像。不太友好的样子。对我之中 只会写BUG的程序猿 来说。还有有点吃力。还需要继续加油学习。
以上案例的源码:demo-test模块下面。
下面这个是我的个人公共号 只会写Bug的程序猿,大家可以关注一下。相互交流学习。
Ross zhang的博客
RossZhang的CSDN地址