Lambda表达式与函数式接口的关系

JDK1.8中Lambda表达式的引入是为了简化使用传统的匿名内部类方式使用函数式接口的写法。
下面给出几个例子解释一下这句话的意思。

1. Runnable接口

在这里插入图片描述

// JDK7时使用匿名内部类的方式实例化函数式接口
new Thread(new Runnable(){// 接口名
	@Override
	public void run(){// 方法名
		System.out.println("Hello");
	}
}).start();
// JDK8 Lambda表达式简化了上述写法
new Thread(
        () -> {
            System.out.print("Hello");
        }
).start();

上述代码跟匿名内部类的作用是一样的,但比匿名内部类更进一步。这里连接口名和函数名都一同省掉了,写起来更加神清气爽。

2. Comparator接口

在这里插入图片描述

// JDK7 使用匿名内部类实例化函数式接口
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, new Comparator<String>(){// 接口名
    @Override
    public int compare(String s1, String s2){// 方法名
        if(s1 == null)
            return -1;
        if(s2 == null)
            return 1;
        return s1.length()-s2.length();
    }
});
// JDK8 Lambda表达式写法
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, (s1, s2) ->{// 省略参数表的类型
    if(s1 == null)
        return -1;
    if(s2 == null)
        return 1;
    return s1.length()-s2.length();
});

上述代码跟匿名内部类的作用是一样的。除了省略了接口名和方法名,代码中把参数表的类型也省略了。这得益于javac的类型推断机制,编译器能够根据上下文信息推断出参数的类型,当然也有推断失败的时候,这时就需要手动指明参数类型了。注意,Java是强类型语言,每个变量和对象都必需有明确的类型。

3. CommandLineRunner接口

在这里插入图片描述
CommandLineRunner是SpringBoot框架中的一个接口。

  //JDK7 使用匿名内部类实例化函数式接口
  @Bean
  public CommandLineRunner run(RestTemplate restTemplate) {
    return new CommandLineRunner() {
      @Override
      public void run(String... args) throws Exception {
        Quote quote = restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
       logger.info(quote.toString());
      }
    };
  }
  //JDK8 Lambda表达式写法
  @Bean
  public CommandLineRunner run(RestTemplate restTemplate) {
    return args -> {
      System.out.println(args[0]);
      Quote quote = restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
      logger.info(quote.toString());
    };
  }

4. 简写的依据

能够使用Lambda的依据是必须有相应的函数接口(函数接口,是指内部只有一个抽象方法的接口)。Comparator接口虽然有两个抽象方法,compare方法和equals方法,但实际被实现的只有compare方法,因为每个类都默认会实现equals方法,因为都继承于Object类,Object中有equals的默认实现。
Lambda表达式另一个依据是类型推断机制,在上下文信息足够的情况下,编译器可以推断出参数表的类型,而不需要显式指名。Lambda表达更多合法的书写形式如下:

// Lambda表达式的书写形式
Runnable run = () -> System.out.println("Hello World");// 1
ActionListener listener = event -> System.out.println("button clicked");// 2
Runnable multiLine = () -> {// 3 代码块
    System.out.print("Hello");
    System.out.println(" Hoolee");
};
BinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4
BinaryOperator<Long> addImplicit = (x, y) -> x + y;// 5 类型推断

个人理解,Lambda表达式最终完成的任务的创建对象。

猜你喜欢

转载自blog.csdn.net/sinat_32336967/article/details/106669680