java8函数式接口(Functional Interface)

介绍

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口可以被隐式转换为 lambda 表达式(箭头函数)。

函数式接口代表的一种契约, 一种对某个特定函数类型的契约。
Lambda表达式不能脱离上下文而存在,它必须要有一个明确的目标类型(interface),而这个目标类型就是某个函数式接口。

java8之前已经存在的函数式接口有很多,比如java.lang.Runnable、java.util.concurrent.Callable、java.util.Comparator等。
而新增加的函数式接口都在java.util.function包下。

Java 不会强制要求你使用 @FunctionalInterface 注解来标记你的接口是函数式接口, 然而,作为API作者, 你可能倾向使用@FunctionalInterface指明特定的接口为函数式接口, 这只是一个设计上的考虑, 可以让用户很明显的知道一个接口是函数式接口。

入门

先来看一个入门的例子就能明白为啥函数式接口是一种契约:

@FunctionalInterface
public interface Predicate<T> {
    //该接口有一个抽象方法test,它接受一个参数t,并且返回boolean
    //如此定义一个抽象方法,就是在约定,我这个抽象方法的实现类,一定是仅有一个参数,并且只会返回一个boolean的值。
    //所以说函数式接口是一种契约。
    boolean test(T t);
}

  

Predicate的使用实例:
//方法evel接受一个列表和一个Predicate接口
//list每个元素会当成 predicate的test方法的参数。
//因为函数式接口是可以使用Lambda表达式的,所以第二个参数这里就可以使用箭头函数了。
public static void eval(List<Integer> list, Predicate<Integer> predicate) {
      //循环list
      for(Integer i: list) {
         //调用predicate的test方法,返回一个boolean值。
         if(predicate.test(i)) {
            System.out.println(i + " ");
         }
          //疑问:Predicate是一个接口啊!那他具体执行的方法(实现类/实现方法)在哪里呢????
          //请看main方法!!!
      }
   }

public static void main(String args[]){
      //定义一个list
      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

      //n -> n%2
      //其实很简单,这个Lambda表达式其实就是Predicate接口的实现:
      //  箭头左边 n 是一个参数, 它会被传递到 Predicate 接口的 test 方法中
      //  而箭头右边 n%2 其实就是这个 test 抽象方法的实现方法,它用来计算输入参数是否是一个偶数。
      //所以整个方法就是用来打印list中的偶数了。
      eval(list, n-> n%2 == 0 );
      System.out.println("输出所有偶数:");

   }

 

新函数式接口

java.util.function中定义了几组类型的函数式接口以及针对基本数据类型的子接口。

  • Predicate -- 传入一个参数,返回一个bool结果, 方法为boolean test(T t)
  • Consumer -- 传入一个参数,无返回值,纯消费。 方法为void accept(T t)
  • Function -- 传入一个参数,返回一个结果,方法为R apply(T t)
  • Supplier -- 无参数传入,返回一个结果,方法为T get()
  • UnaryOperator -- 一元操作符, 继承Function,传入参数的类型和返回类型相同。
  • BinaryOperator -- 二元操作符, 传入的两个参数的类型和返回类型相同, 继承BiFunction

函数式接口中的抽象方法

在上面介绍中,说到函数式接口有且仅有一个抽象方法,其实是不正确的,因为函数式接口中可以额外定义多个抽象方法,但这些抽象方法签名必须和Object类的 public方法一样,只是我们一般不会再重新定义这些方法。

@FunctionalInterface
public interface ObjectMethodFunctionalInterface {
	void count(int i);

	String toString(); //same to Object.toString
	int hashCode(); //same to Object.hashCode
	boolean equals(Object obj); //same to Object.equals
}

 

声明异常

函数式接口的抽象方法可以声明 可检查异常(checked exception)。 在调用目标对象的这个方法时必须catch这个异常。

@FunctionalInterface
interface InterfaceWithException {
	//声明异常
	void apply(int i) throws Exception;
}

  

捕获异常:
public class FunctionalInterfaceWithException {
	public static void main(String[] args) {
		InterfaceWithException target = i -> {};
		try {
			target.apply(10);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

非法抛出异常:



@FunctionalInterface
interface InterfaceWithException {
	//没有声明异常
	void apply(int i);
}
public class FunctionalInterfaceWithException {
	public static void main(String[] args) {
		//函数式接口没有声明异常,
		//而 Lambda中却抛出了异常,此时是无法通过编译的!!!
		InterfaceWithException target = i -> {throw new Exception();};
	}
}
  
 

静态方法

函数式接口中除了那个抽象方法外还可以包含静态方法。
Java 8以前的规范中接口中不允许定义静态方法。 静态方法只能在类中定义。 但是到了Java 8,可以定义静态方法。

默认方法

Java 8中允许接口实现方法, 而不是简单的声明, 这些方法叫做默认方法,使用特殊的关键字default。
因为默认方法不是抽象方法,所以不影响我们判断一个接口是否是函数式接口。

function包中的类的函数式接口概览

  1. BiConsumer<T,U> 代表了一个接受两个输入参数的操作,并且不返回任何结果
  2. BiFunction<T,U,R> 代表了一个接受两个输入参数的方法,并且返回一个结果
  3. BinaryOperator 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
  4. BiPredicate<T,U> 代表了一个两个参数的boolean值方法
  5. BooleanSupplier 代表了boolean值结果的提供方
  6. Consumer 代表了接受一个输入参数并且无返回的操作
  7. DoubleBinaryOperator 代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
  8. DoubleConsumer 代表一个接受double值参数的操作,并且不返回结果。
  9. DoubleFunction 代表接受一个double值参数的方法,并且返回结果
  10. DoublePredicate 代表一个拥有double值参数的boolean值方法
  11. DoubleSupplier 代表一个double值结构的提供方
  12. DoubleToIntFunction 接受一个double类型输入,返回一个int类型结果。
  13. DoubleToLongFunction 接受一个double类型输入,返回一个long类型结果
  14. DoubleUnaryOperator 接受一个参数同为类型double,返回值类型也为double 。
  15. Function<T,R> 接受一个输入参数,返回一个结果。
  16. IntBinaryOperator 接受两个参数同为类型int,返回值类型也为int 。
  17. IntConsumer 接受一个int类型的输入参数,无返回值 。
  18. IntFunction 接受一个int类型输入参数,返回一个结果 。
  19. IntPredicate :接受一个int输入参数,返回一个布尔值的结果。
  20. IntSupplier 无参数,返回一个int类型结果。
  21. IntToDoubleFunction 接受一个int类型输入,返回一个double类型结果 。
  22. IntToLongFunction 接受一个int类型输入,返回一个long类型结果。
  23. IntUnaryOperator 接受一个参数同为类型int,返回值类型也为int 。
  24. LongBinaryOperator 接受两个参数同为类型long,返回值类型也为long。
  25. LongConsumer 接受一个long类型的输入参数,无返回值。
  26. LongFunction 接受一个long类型输入参数,返回一个结果。
  27. LongPredicate R接受一个long输入参数,返回一个布尔值类型结果。
  28. LongSupplier 无参数,返回一个结果long类型的值。
  29. LongToDoubleFunction 接受一个long类型输入,返回一个double类型结果。
  30. LongToIntFunction 接受一个long类型输入,返回一个int类型结果。
  31. LongUnaryOperator 接受一个参数同为类型long,返回值类型也为long。
  32. ObjDoubleConsumer 接受一个object类型和一个double类型的输入参数,无返回值。
  33. ObjIntConsumer 接受一个object类型和一个int类型的输入参数,无返回值。
  34. ObjLongConsumer 接受一个object类型和一个long类型的输入参数,无返回值。
  35. Predicate 接受一个输入参数,返回一个布尔值结果。
  36. Supplier 无参数,返回一个结果。
  37. ToDoubleBiFunction<T,U> 接受两个输入参数,返回一个double类型结果
  38. ToDoubleFunction 接受一个输入参数,返回一个double类型结果
  39. ToIntBiFunction<T,U> 接受两个输入参数,返回一个int类型结果。
  40. ToIntFunction 接受一个输入参数,返回一个int类型结果。
  41. ToLongBiFunction<T,U> 接受两个输入参数,返回一个long类型结果。
  42. ToLongFunction 接受一个输入参数,返回一个long类型结果。
  43. UnaryOperator 接受一个参数为类型T,返回值类型也为T

作者:DoubleDragon
链接:https://juejin.im/post/5c77b354e51d457143522e13
来源:掘金

原文地址:https://www.cnblogs.com/ampl/p/11441129.html

时间: 2024-11-10 07:50:03

java8函数式接口(Functional Interface)的相关文章

Java 8 函数式接口 - Functional Interface

阅读目录 什么是函数式接口(Functional Interface) 函数式接口用途 关于@FunctionalInterface注解 函数式接口里允许定义默认方法 函数式接口里允许定义静态方法 函数式接口里允许定义java.lang.Object里的public方法 JDK中的函数式接口举例 参考资料 什么是函数式接口(Functional Interface) 其实之前在讲Lambda表达式的时候提到过,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法. 这种

java代码之美(14)---Java8 函数式接口

Java8 函数式接口 之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加简洁. 一.概念 1.什么是函数式接口 概念 所谓的函数式接口, 当然首先是一个接口, 然后就是在这个接口里面 只能有一个抽象方法. 有关函数式接口,有个专门的注解叫:@FunctionalInterface.该注解主要特点有: 1.该注解只能标记在"有且仅有一个抽象方法"的接口上,表示函

[二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * 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 Specificat

Java8函数式接口以及lambda表达式实践

最近重新深入了解和学习了Java8的函数式接口以及lambda表达式,发现以前写的代码大多都是伪-函数表达式,因此重新精炼了一下的这部分代码,仅供参考,如有更好的方式,欢迎在评论区留言. 1.计算订单总金额 订单总金额一般是在后台循环叠加每个购买商品的金额已获取到,通常的方式如下 BigDecimal totalAmount = new BigDecimal(0); for (VenditionProduct venditionProduct : venditionVo.getVendition

Java8函数式接口/Lambda表达式/接口默认方法/接口静态方法/接口冲突方法重写/lambda表达式指定泛型类型等

一:函数式接口 1.函数式接口的概念就是此接口必须有且只能有一个抽象方法,可以通过@FunctionalInterface来显示规定(类似@Override),但是没有此注解的但是只有一个抽象方法的接口也是函数式接口:(接口也和类一样有包访问权限,但是内部的方法则默认是public) @FunctionalInterface public interface IFoo{ void print(); }  // 就是一个最简单的函数式接口,但是如果再有个如void print2()抽象方法则这个接

Java8函数式接口简介

一.函数式接口 1. 可以使用注解@FunctionalInterface 2. 函数式接口有且仅有一个抽象方法:如果一个接口里只有一个抽象方法,这个接口可以作为函数式接口 3. 可以有0个或多个非抽象方法 4. 可以被隐式转换为lambda表达式 5. 函数式接口的实例 a. lambda表达式:提供参数列表,代码块主体,必须依附于函数式接口的实例对象 b. 方法引用,把函数当参数使用 6. java8允许在接口中加入具体方法/default方法/static方法,default方法 二.Su

乐字节-Java8核心特性实战之函数式接口

什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. java8引入@FunctionalInterface 注解声明该接口是一个函数式接口. 语法 抽象方法有且仅有一个 接口使用@FunctionalInterface 注解进行标注 接口中可以存在默认方法和静态方法实现 如下形式: /** * 定义函数式

Java 8 新特性-菜鸟教程 (3) -Java 8 函数式接口

Java 8 函数式接口 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. 函数式接口可以被隐式转换为lambda表达式. 函数式接口可以现有的函数友好地支持 lambda. JDK 1.8之前已有的函数式接口: java.lang.Runnable java.util.concurrent.Callable java.security.PrivilegedAction java.util.Comparator java.io.

009-jdk1.8版本新特性一-展方法,Lambda表达式,函数式接口、方法引用构造引用

一.JDK1.8 名称:Spider(蜘蛛) 发布日期:2014-03-18 新特性: 1.1.扩展方法[接口的默认方法] Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法. 在Java中只有单继承,如果要让一个类赋予新的特性,通常是使用接口来实现,在C++中支持多继承,允许一个子类同时具有多个父类的接口与功能,在其他语言中,让一个类同时具有其他的可复用代码的方法叫做mixin.新的Java 8 的这个特新在编译器实现的角度上来说更