Java8新特性(二) 函数式接口

本文深入解析Java8中的函数式接口概念,包括@FunctionalInterface注解的作用、Lambda表达式与函数式接口的关系,以及Java内置的四大核心函数式接口(Consumer、Supplier、Function、Predicate)的详细用法。通过实例演示Predicate接口的应用,帮助读者掌握函数式编程在Java中的实践。

1、什么是函数式接口

  • 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)。
  • 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
  • java.util.function包下定义了java 8 的丰富的函数式接口。

1.1、关于@FunctionalInterface注解

Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。

正确例子,没有报错:

@FunctionalInterface
interface GreetingService {
    void sayMessage(String message);
}

错误例子,接口中包含了两个抽象方法,违反了函数式接口的定义,Eclipse 报错提示其不是函数式接口。

注意:加不加 @FunctionalInterface 对于接口是不是函数式接口没有影响,该注解只是提醒编译器去检查该接口是否仅包含一个抽象方法。

1.2、如何理解函数式接口

  • Java诞生日起就是一直倡导“一切皆对象”,在java里面面向对象(OOP)编程是一切。但是随着pythonscala等语言的兴起和新技术的挑战,java不得不做出调整以便支持更加广泛的技术要求,也java不但可以支持OOP还可以支持OOF(面向函数编程)
  • 在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是Java8中,有所不同。在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口
  • 简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。所以以前用匿名内部类表示的现在都可以用Lambda表达式来写。

2、自定义函数式接口

函数式接口中使用泛型:

3、作为参数传递 Lambda表达式

作为参数传递 Lambda表达式:

作为参数传递  Lambda表达式:为了将  Lambda  表达式作为参数传递,接收 Lambda表达式的参数类型必须是与该Lambda表达式兼容的函数式接口的类型。

3、Java内置四大核心函数式接口

函数式接口

参数类型

返回类型

用途

Consumer<T>

消费型接口

T

void

对类型为T的对象应用操作,包含方法

void accept(T t)

Supplier<T>

供给型接口

T

返回类型为T的对象,包含方法T get()

Function<T, R>

函数型接口

T

R

对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法R apply(T t)

Predicate<T>

断定型接口

T

boolean

确定类型为T的对象是否满足某约束,并返回 boolean 值。包含方法

boolean test(T t)

4、其他接口

函数式接口

参数类型

返回类型

用途

BiFunction<T, U, R>

T, U

R

对类型为 T, U 参数应用操作,返回 R 类型的结果。包含方法 

R apply(T t, U u);

UnaryOperator<T>

(Function子接口)

T

T

对类型为T的对象进行一元运算,并返回T类型的结果。包含方法

T apply(T t);

BinaryOperator<T>

(BiFunction 子接口)

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)

BiPredicate<T,U>

T,U

boolean

包含方法为  boolean test(T t,U u)

ToIntFunction<T>

ToLongFunction<T>

ToDoubleFunction<T>

T

int

long

double

分别计算intlongdouble、值的函数

IntFunction<R>

LongFunction<R>

DoubleFunction<R>

int

long

double

R

参数分别为intlongdouble 类型的函数

5、函数式接口实例

Predicate <T> 接口是一个函数式接口,它接受一个输入参数 T,返回一个布尔值结果。
该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。
该接口用于测试对象是 true 或 false。
我们可以通过以下实例(Java8Tester.java)来了解函数式接口 Predicate <T> 的使用:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
 
public class Java8Tester {
   public static void main(String args[]){
      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        
      // Predicate<Integer> predicate = n -> true
      // n 是一个参数传递到 Predicate 接口的 test 方法
      // n 如果存在则 test 方法返回 true
        
      System.out.println("输出所有数据:");
        
      // 传递参数 n
      eval(list, n->true);
        
      // Predicate<Integer> predicate1 = n -> n%2 == 0
      // n 是一个参数传递到 Predicate 接口的 test 方法
      // 如果 n%2 为 0 test 方法返回 true
        
      System.out.println("输出所有偶数:");
      eval(list, n-> n%2 == 0 );
        
      // Predicate<Integer> predicate2 = n -> n > 3
      // n 是一个参数传递到 Predicate 接口的 test 方法
      // 如果 n 大于 3 test 方法返回 true
        
      System.out.println("输出大于 3 的所有数字:");
      eval(list, n-> n > 3 );
   }
    
   public static void eval(List<Integer> list, Predicate<Integer> predicate) {
      for(Integer n: list) {
        
         if(predicate.test(n)) {
            System.out.println(n + " ");
         }
      }
   }
}

执行以上脚本,输出结果为:

$ javac Java8Tester.java 
$ java Java8Tester
输出所有数据:
1 
2 
3 
4 
5 
6 
7 
8 
9 
输出所有偶数:
2 
4 
6 
8 
输出大于 3 的所有数字:
4 
5 
6 
7 
8 
9 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值