Java8新特性之lambda 表达式与函数式接口

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18948359/article/details/85723142

简介

lambda 表达式的类型,也被称为“目标类型(target type)”,lambda 表达式的目标类型必须是“函数式接口(functional interface)”。函数式接口代表只包含一个抽象方法的接口。函数式接口可以包含多个默认方法、类方法,但是只能声明一个抽象方法。

从这里可以看到,Java 8 对接口增加了 static 以及 default 关键字,就可以说的通了。为了让 @FunctionalInterface(函数式接口)使用起来更加方便。

Java8 专门为函数式接口提供了 @FunctionalInterface 注解,该注解通常放在接口定义前面,该注解对程序功能没有任何作用,他用于告诉编译器执行更加严格的检查——检查该接口必须是函数式接口,否则编译器就会报错。

代码示例

lambda 表达式的限制

由于 lambda 表达式的结果就是被当成对象,因此程序中完全可以使用 lambda 表达式进行赋值。

// Runnable 接口中只包含一个无参的方法
// lambda 表达式代表的匿名方法实现了 Runnable 接口中的唯一的、无参方法
// 下面的语句创建了一个 Runnable 对象
Runnable r = () -> {
    for( int i=0; i<100; i++ ){
        System.out.println();
    }
}

lambda 表达式实现的是匿名方法——因此它只能实现特定函数式接口中的唯一方法。因此可以看到 lambda 表达式有如下两个限制。

  • lambda 表达式的目标类型必须是明确的函数式接口。
  • lambda 表达式只能为函数式接口创建对象。lambda 表达式只能实现一个方法,因此它只能为只有一个抽象方法的接口(函数式接口)创建对象。

错误的代码

// 这段代码是错误的
// 会报:不兼容的类型: object 不是函数接口
Object obj = () -> {
    for( int i=0; i<100; i++ ){
        System.out.println();
    }
}

从上面的代码将 lambda 表达式赋值给 Object 变量,编译器只能确定该 Lambda 表达式的类型为 Object,而 Object 不是接口,因此会报错。

因此为了保证 lambda 表达式的目标类型必须要是明确的函数式接口。有下面三种常见的方式:

  • 将 lambda 表达式赋值给函数式接口类型的变量
  • 将 lambda 表达式作为函数式接口类型的参数传递给某个方法
  • 使用函数式接口对 lambda 表达式进行强制类型转换
// 对lambda表达式 使用强制类型转换
Object obj = (Runnable)() -> {
    for( int i=0; i<100; i++ ){
        System.out.println();
    }
}

Java 8 中的4类内建函数式接口

  • XxxFunction,功能型接口。 语法:public interface Function<T,R>{public R apply(T t);}。该接口通常用于对指定数据进行转换处理。 apply() 抽象方法,对参数进行处理、转换。然后返回一个新的值。
  • XxxConsumer,消费型接口。语法:public interface Consumer<T>{public void accept(T t);}。该方法与 apply() 方法类似,也负责对参数进行处理,只是该方法不会返回处理结果。
  • XxxSupplier,供给型接口。语法:public interface Supplier<T>{public T get()}。这类接口通常含有 getAsXxx() 接口。该方法不需要输入参数,该方法会按照某种逻辑算法(逻辑算法由 lambda 表达式实现)返回一个数据。
  • XxxPredicate,断言型接口。语法:public interface Predicate<T>{public boolean test(T t);}。该方法通常用来对参数进行某种判断是否满足特定条件,经常用于筛选数据。

代码实例

功能型接口

import java.util.function.Function;
 
public class Demo {
	public static void main(String[] args) {
		Function<String, Boolean> fun = "hello world"::startsWith;
		System.out.println(fun.apply("hello"));
	}
}

详细说明

/**
 * Function测试
 */
public static void functionTest() {
    Function<Integer, Integer> f = i -> i + 10;
    Function<Integer, Integer> g = s -> s * 2;

    /**
     * 下面表示在执行F时,先执行G,并且执行F时使用G的输出当作输入。
     * 相当于以下代码:
     * Integer a = g.apply(1);
     * System.out.println(f.apply(a));
     */
    System.out.println(f.compose(g).apply(1));

    /**
     * 表示执行F的Apply后使用其返回的值当作输入再执行G的Apply;
     * 相当于以下代码
     * Integer a = f.apply(1);
     * System.out.println(g.apply(a));
     */
    System.out.println(f.andThen(g).apply(1));

    /**
     * identity方法会返回一个不进行任何处理的Function,即输出与输入值相等; 
     */
    System.out.println(Function.identity().apply("a"));
}

消费型接口

import java.util.function.Consumer;;
 
class MyDemo{
	public void print(String str) {
		System.out.println(str);
	}
}
public class Demo {
	public static void main(String[] args) {
		Consumer<String> con = new MyDemo()::print;
		con.accept("Good!");
		
		Consumer<String> con1 = System.out::println;
		con1.accept("Nice!");
	}
}

详细说明

public static void consumerTest() {
    Consumer f = System.out::println;
    Consumer f2 = n -> System.out.println(n + "-F2");

    //执行完F后再执行F2的Accept方法
    f.andThen(f2).accept("test");

    //连续执行F的Accept方法
    f.andThen(f).andThen(f).andThen(f).accept("test1");
}

供给型接口

import java.util.function.Supplier;
 
public class Demo {
	public static void main(String[] args) {
		Supplier<String> sup = "hello".substring(2, 5)::toUpperCase;
		String str = sup.get();
		System.out.println(str);
	}
}

断言型接口

import java.util.function.Predicate;
 
public class Demo {
	public static void main(String[] args) {
		Predicate<String> pre = "Good"::endsWith;
		System.out.println(pre.test("od"));
	}
}

详细说明

/**
 * Predicate测试
 */
private static void predicateTest() {
    Predicate<String> p = o -> o.equals("test");
    Predicate<String> g = o -> o.startsWith("t");

    /**
     * negate: 用于对原来的Predicate做取反处理;
     * 如当调用p.test("test")为True时,调用p.negate().test("test")就会是False;
     */
    Assert.assertFalse(p.negate().test("test"));

    /**
     * and: 针对同一输入值,多个Predicate均返回True时返回True,否则返回False;
     */
    Assert.assertTrue(p.and(g).test("test"));

    /**
     * or: 针对同一输入值,多个Predicate只要有一个返回True则返回True,否则返回False
     */
    Assert.assertTrue(p.or(g).test("ta"));
}

猜你喜欢

转载自blog.csdn.net/qq_18948359/article/details/85723142