您的位置:首页 > 编程语言 > Java开发

Java8学习笔记(一)-初步认识Lambda表达式

2017-07-27 00:00 961 查看
Lambda是什么?
  In programming languages such as Lisp,Pythson and Ruby Lambda is an operator used to denote anonymous function or closures,following the usage of lambda calculus

为什么要使用Lambda表达式?

  在java中,我们无法将函数作为参数传递给一个方法,也无法声明返回一个函数的方法

  在javascript中,函数参数是一个函数,返回值是另一个函数的情况是非常常见的,javascript是一门非常典型的函数式语言

Java匿名内部类案例带来的问题

1 public class Test {
2     public static void main(String[] args) {
3         JFrame jframe = new JFrame("测试窗口");
4         JButton jbtn   = new JButton("测试按钮");
5         jbtn.addActionListener(new ActionListener() {
6             public void actionPerformed(ActionEvent arg0) {
7                 System.out.println("测试按钮被点击了");
8             }
9         });
10         jframe.add(jbtn);
11         jframe.setVisible(true);
12     }
13 }


以上代码,关键部分就是执行按钮被点击后的核心操作,但是却使用了大量的冗余代码,那么使用Lambda表达式可以有效地简化以上代码

1 jbtn.addActionListener(event -> {
2             System.out.println("按钮被点击了");
3 });


event的数据类型是java7开始加入的类型推断机制,有些时候是推断不出来的,需要我们自己显示定义


1 jbtn.addActionListener((ActionEvent e) -> {
2             System.out.println("按钮被点击了");
3             System.out.println("不使用类型推断机制");
4 });


 Lambda表达式的基本结构

(param1,param2,...)->{
statemnt;
}


再看一个案例

 

1 package cn.org.kingdom.jdk8;
2
3 import java.util.Arrays;
4 import java.util.List;
5 import java.util.function.Consumer;
6
7 public class Test2 {
8     public static void main(String[] args) {
9         List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
10         // 最早的遍历方式
11         for (int i = 0; i < list.size(); i++) {
12             System.out.println(list.get(i));
13         }
14         System.out.println("-------------------");
15         // 增强的for循环的方式
16         for (Integer i : list) {
17             System.out.println(i);
18         }
19         System.out.println("*********************");
20         list.forEach(new Consumer<Integer>() {
21             @Override
22             public void accept(Integer t) {
23                 System.out.println(t);
24             }
25         });
26
27     }
28 }


下面咱们研究一下Consumer接口

1 /**
2  * Represents an operation that accepts a single input argument and returns no
3  * result. Unlike most other functional interfaces, {@code Consumer} is expected
4  * to operate via side-effects.
5  *
6  * <p>This is a <a href="package-summary.html">functional interface</a>
7  * whose functional method is {@link #accept(Object)}.
8  *
9  * @param <T> the type of the input to the operation
10  *
11  * @since 1.8
12  */
13 @FunctionalInterface
14 public interface Consumer<T> {
15
16     /**
17      * Performs this operation on the given argument.
18      *
19      * @param t the input argument
20      */
21     void accept(T t);
22
23     /**
24      * Returns a composed {@code Consumer} that performs, in sequence, this
25      * operation followed by the {@code after} operation. If performing either
26      * operation throws an exception, it is relayed to the caller of the
27      * composed operation.  If performing this operation throws an exception,
28      * the {@code after} operation will not be performed.
29      *
30      * @param after the operation to perform after this operation
31      * @return a composed {@code Consumer} that performs in sequence this
32      * operation followed by the {@code after} operation
33      * @throws NullPointerException if {@code after} is null
34      */
35     default Consumer<T> andThen(Consumer<? super T> after) {
36         Objects.requireNonNull(after);
37         return (T t) -> { accept(t); after.accept(t); };
38     }
39 }


对于Comsume接口上面有一个@FunctionalInterface-->函数式接口,那么什么是函数式接口呢?

咱们再来看一看FunctionalInterface的源码定义

1 package java.lang;
2
3 import java.lang.annotation.*;
4
5 /**
6  * An informative annotation type used to indicate that an interface
7  * type declaration is intended to be a <i>functional interface</i> as
8  * defined by the Java Language Specification.
9  *
10  * Conceptually, a functional interface has exactly one abstract
11  * method.  Since {@linkplain java.lang.reflect.Method#isDefault()
12  * default methods} have an implementation, they are not abstract.  If
13  * an interface declares an abstract method overriding one of the
14  * public methods of {@code java.lang.Object}, that also does
15  * <em>not</em> count toward the interface's abstract method count
16  * since any implementation of the interface will have an
17  * implementation from {@code java.lang.Object} or elsewhere.
18  *
19  * <p>Note that instances of functional interfaces can be created with
20  * lambda expressions, method references, or constructor references.
21  *
22  * <p>If a type is annotated with this annotation type, compilers are
23  * required to generate an error message unless:
24  *
25  * <ul>
26  * <li> The type is an interface type and not an annotation type, enum, or class.
27  * <li> The annotated type satisfies the requirements of a functional interface.
28  * </ul>
29  *
30  * <p>However, the compiler will treat any interface meeting the
31  * definition of a functional interface as a functional interface
32  * regardless of whether or not a {@code FunctionalInterface}
33  * annotation is present on the interface declaration.
34  *
35  * @jls 4.3.2. The Class Object
36  * @jls 9.8 Functional Interfaces
37  * @jls 9.4.3 Interface Method Body
38  * @since 1.8
39  */
40 @Documented
41 @Retention(RetentionPolicy.RUNTIME)
42 @Target(ElementType.TYPE)
43 public @interface FunctionalInterface {}
翻译如下:
  一个通知性的注解类型用于表示一个接口类型声明只在成为一个函数式接口(这个函数式接口是由java语言规范所定义的)
  从概率上来看,一个函数式接口只有一个精确的抽象方法,由于java.reflect.method的isDefault方法有一个默认的实现,因此他们不是抽象的,如果一个接口声明了一个抽象方法重写了Object类的方法,它们也不能增加函数式接口中抽象方法的数量,因为接口的任意实现都有来自于object类或者其他地方的任意实现
  注意一个函数式接口的实例可以通过lambda表达式、方法引用、构造引用来创建
  如果一个类型被这种类型所表示,那么编译器被要求强制生成一个错误信息:
  然而编译器对待任何一个接口,只要这个接口满足了函数式接口定义的要求,依然会将该接口当成一个函数式接口,而不管这个接口上是否加上了这么一个FunctionalInterface注解


总结:关于函数式接口

1.如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口

2.如果我们在某个接口上声明了FunctionalInterface注解,那么编译器就会按照函数式接口的定义来要求该接口

3.如果某个接口只有一个抽象方法,但我们并没有给该接口声明Functional注解,那么编译器依旧会将该接口看做函数式接口

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: