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匿名内部类案例带来的问题
以上代码,关键部分就是执行按钮被点击后的核心操作,但是却使用了大量的冗余代码,那么使用Lambda表达式可以有效地简化以上代码
Lambda表达式的基本结构
再看一个案例
下面咱们研究一下Consumer接口
对于Comsume接口上面有一个@FunctionalInterface-->函数式接口,那么什么是函数式接口呢?
咱们再来看一看FunctionalInterface的源码定义
总结:关于函数式接口
1.如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
2.如果我们在某个接口上声明了FunctionalInterface注解,那么编译器就会按照函数式接口的定义来要求该接口
3.如果某个接口只有一个抽象方法,但我们并没有给该接口声明Functional注解,那么编译器依旧会将该接口看做函数式接口
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注解,那么编译器依旧会将该接口看做函数式接口
相关文章推荐
- 【Java学习笔记之三十一】详解Java8 lambda表达式
- Java8学习笔记----Lambda表达式 (转)
- Java Lambda 表达式学习笔记
- Java8学习笔记 — 【Lambda表达式】
- java8学习笔记之lambda表达式
- java lambda表达式学习笔记
- Java学习笔记-Lambda表达式及內建函数式接口
- [学习笔记] Java核心技术 卷一:基础知识 接口、lambda表达式与内部类(三)
- java8新特性学习笔记(一) Lambda表达式
- Java8学习笔记之Lambda表达式
- java lambda表达式学习笔记
- 一、JAVA8学习笔记 Lambda表达式快速入门
- java lambda表达式 闭包学习笔记
- java8学习之Lambda表达式深入与流初步
- java8学习之Lambda表达式初步与函数式接口
- Java8 学习笔记--函数式接口与lambda表达式的关系
- 黑马程序员 java学习笔记--正则表达式
- concurrency runtime学习笔记之一:Lambda表达式
- Memcached学习笔记——windows上初步使用(与java结合)