简单易懂的java8新特性之lambda表达式知识总结

一、概念

从本质上来说,它就是一个匿名函数,可以用来直接实现接口中的方法,从而简化代码。但是Lambda有一个限制,不能实现接口中的所有方法,所以Lambda表达式只能用于有且仅有一个必须需要实现的方法接口,这里需要注意必须需要实现这六个字。

public interface Printer {
//有一个需要实现的方法,可以使用Lambda表达式
	void print();
}
public interface Printer {
//有一个需要实现的方法,可以使用Lambda表达式
	void print();
	//这里虽然有一个方法,但接口提供了默认实现,因此不是必须要实现的
	default void printDetail(){}
}
public interface Printer {
//有一个需要实现的方法,可以使用Lambda表达式
	void print();
//这里虽然有一个需要实现的方法,但不是必须要实现的,因为toString()是Object类中的.
String toString();
}
public interface Printer {
//有一个需要实现的方法,可以使用Lambda表达式
	void print();
//这里虽然有一个需要实现的方法,但不是必须要实现的,因为toString()是Object类中的.
String toString();
}

像这种只有一个必须要实现的方法的接口,在java8中称之为函数式接口,在定义接口时可以在接口名上方加上@FunctionInterface标签,用于验证此接口是否为函数式接口。如果这个接口定义好之后不是函数式接口,那么接口名处会报错。
在使用Lambda表达式的时候,不需要关注方法名,只需要关注方法参数和返回值即可。基本语法很简单:

(参数列表)->{
	方法体
};

二、用法比较

java中实现接口的方式在java8之前有两种:定义接口的实现类,使用匿名类,但Lambda表达式相比于这种方法都简单很多。以上文的Printer接口为例,实现如下:

2.1 实现类

class PrinterImpl implements Printer{

	@Override
	public void print() {
		System.out.println("Hello World");
	}

}

2.2 匿名类

class PrinterAnonymous {

	Printer printer = new Printer() {

		@Override
		public void print() {
			System.out.println("Hello World");

		}
	};

}

2.3 Lambda

class PrinterLambda{
	Printer p = ()-> System.out.println("Hello World");
}

比较上文三种实现方式,很显示Lambda的实现比前两种简单很多。

三、基本用法

3.1 无参数无返回值接口方法

@FunctionalInterface
public interface Printer {
	void print();
}
public class Tester {
	public static void main(String[] args) {
		// 方法一,无返回值的情况,方法体只有一条语句,可以省略大括号
		Printer p1 = () -> System.out.println("Hello World 1");
		p1.print();
		// 方法二,标准定义
		Printer p2 = () -> {
			System.out.println("Hello World 2");
		};
		p2.print();
	}
}

3.2 一个参数无返回值接口方法

@FunctionalInterface
public interface Printer {
	void print(String str);
}

public class Tester {

	public static void main(String[] args) {
		// 方法一,无返回值的情况,方法体只有一条语句,可以省略大括号
		//因为这里只有一个参数,小括号也可以省略,小括号省略的前提是:有且仅有一个参数
		//Printer p1 = s -> System.out.println(s);
		Printer p1 = (s) -> System.out.println(s);
		p1.print("Hello World 1");
		// 方法二,无返回值的情况,方法体只有一条语句,可以省略大括号
		Printer p2 = (String s) -> System.out.println(s);
		p2.print("Hello World 2");
		// 方法三,标准定义
		Printer p3 = (String s) -> {
			System.out.println(s);
		};
		p3.print("Hello World 3");
	}
}

3.3 多个参数无返回值接口方法

@FunctionalInterface
public interface Printer {
	void print(String str1,String str2);
}

public class Tester {

	public static void main(String[] args) {
		// 方法一,无返回值的情况,方法体只有一条语句,可以省略大括号
		//参
		Printer p1 = (s1,s2) -> System.out.println(s1+" "+s2);
		p1.print("Hello World 1","Java 1");
		// 方法二,无返回值的情况,方法体只有一条语句,可以省略大括号
		Printer p2 = (String s1,String s2) -> System.out.println(s1+" "+s2);
		p2.print("Hello World 2","Java 2");
		// 方法三,标准定义
		Printer p3 = (String s1,String s2) -> {
			System.out.println(s1+" "+s2);
		};
		p3.print("Hello World 3","Java 3");

	}

}

3.4 无参数有返回值接口方法

@FunctionalInterface
public interface Printer {
	boolean print();
}

public class Tester {

	public static void main(String[] args) {
		// 方法一,有返回值的情况,只有一条语句,return关键字的有无决定能否活力大括号
		Printer p1 = () ->  true;
		boolean has1 = p1.print();
		System.out.println(has1);//测试返回结果
		// 方法二,标准定义
		Printer p2 = () -> {return true;};
		boolean has2 = p2.print();
		System.out.println(has2);//测试返回结果

	}
}

3.5 一个参数有返回值接口方法

@FunctionalInterface
public interface Printer {
	boolean print(boolean good);
}
public class Tester {

	public static void main(String[] args) {
		// 方法一,有返回值的情况,只有一条语句,return关键字的有无决定能否活力大括号
	   //因为这里只有一个参数,小括号也可以省略,小括号省略的前提是:有且仅有一个参数
	   //Printer p1 = good ->  good;
		Printer p1 = (good) ->  good;
		boolean has1 = p1.print(true);
		System.out.println(has1);
		// 方法二,标准定义
		Printer p2 = (good) -> {return good;};
		boolean has2 = p2.print(false);
		System.out.println(has2);

	}
}

3.6 多个参数有返回值接口方法

@FunctionalInterface
public interface Printer {
	boolean print(boolean good1,boolean good2);
}

public class Tester {

	public static void main(String[] args) {
		// 方法一,有返回值的情况,只有一条语句,return关键字的有无决定能否活力大括号
		Printer p1 = (good1,good2) ->  good1;
		boolean has1 = p1.print(true,false);
		System.out.println(has1);
		// 方法二,标准定义
		Printer p2 = (good1,good2) -> {return good1;};
		boolean has2 = p2.print(false,false);
		System.out.println(has2);

	}
}

四、函数引用

在实现一个接口的方法时,如果现有的其他地方的某个函数已经实现了接口方法的逻辑,可以使用方法引用直接将这个逻辑引用过来。

4.1 静态方法引用

语法:

接口名 变量名 = 类 ::已实现的方法

注意事项:

  • 在引用的方法后面,不要添加小括号
  • 引用的这个方法,参数和返回值,必须要跟接口中定义的一致

示例:
Printer 需要实现的方法在Checker中有同样的实现,这样就可以直接引用过来

@FunctionalInterface
public interface Printer {
	String print(boolean good1,boolean good2);
}

public class Checker {
	public static String check(boolean a,boolean b) {
		if(a && b) {
			return "Java is good";
		}else if (!a && b) {
			return "Java is better";
		}
		return "Java is best";
	}
}
public class Tester {

	public static void main(String[] args) {
		Printer p1 = Checker::check;//用类名来引用
		System.out.println(p1.print(true, true));

	}
}

4.2 非静态方法引用

语法:

接口名 变量名 = 对象 ::静态方法

注意事项:

  • 在引用的方法后面,不要添加小括号
  • 引用的这个方法,参数和返回值,必须要跟接口中定义的一致

示例:
Printer 需要实现的方法在Checker中有同样的实现,这样就可以直接引用过来

@FunctionalInterface
public interface Printer {
	String print(boolean good1,boolean good2);
}

public class Checker {
	public String check(boolean a,boolean b) {
		if(a && b) {
			return "Java is good";
		}else if (!a && b) {
			return "Java is better";
		}
		return "Java is best";
	}
}
public class Tester {

	public static void main(String[] args) {
		Printer p1 = new Checker()::check;//必须用对象来引用
		System.out.println(p1.print(true, true));

	}
}

4.3 构造方法的引用

如果一个函数式接口中定义的方法仅仅是为了得到一个对象,此时我们就可以使用构造方法的引用,简化这个方法的实现
语法:

接口名 变量名 = 类名 ::new

注意事项:
可以通过接口中的方法参数,区分引用不同的构造方法
示例:

@FunctionalInterface
public interface Printer1 {
	Checker getCheck();
}

@FunctionalInterface
public interface Printer2 {
	Checker getCheck(int a);
}

public class Checker {
	int times;
	public Checker() {
		System.out.println("I am none parameter");
	}

	public Checker(int a) {
		System.out.println("I have one parameter");
	}
}

public class Tester {

	public static void main(String[] args) {
		//引用无参构造方法
		Printer1 p1 = Checker::new;
		p1.getCheck();
		//引用有参构造方法
		Printer2 p2 = Checker::new;
		p2.getCheck(1);

	}
}

4.4 对象方法的特殊引用

如果实现某些接口的时候,Lambda表达式中包含了某一个对象,此时方法体中,直接使用这个对象调用它的某一个方法就可以完成整个的逻辑。其他的参数,可以作为调用方法的参数。此时,可以对这种实现进行简化。
示例:

@FunctionalInterface
public interface Printer1 {
	int getCheck(Checker checker);
}

@FunctionalInterface
public interface Printer2 {
	void setCheck(Checker checker, int a);
}

public class Tester {

	public static void main(String[] args) {
		Checker checker = new Checker();
		checker.setTimes(100);
		// 没有简化前,按照之前的方法使用lambda表达式
		Printer1 p1 = x -> x.getTimes();
		System.out.println(p1.getCheck(checker));//测试

		// 简化之后
		Printer1 p11 = Checker::getTimes;
		System.out.println(p11.getCheck(checker));//测试

		// 没有简化前,按照之前的方法使用lambda表达式
		Printer2 p2 = (x,y)-> x.setTimes(y);
		p2.setCheck(checker, 50);
		System.out.println(checker.getTimes());//测试
		// 简化之后
		Printer2 p22 = Checker::setTimes;
		p22.setCheck(checker, 30);
		System.out.println(checker.getTimes());//测试

	}
}

五、注意

当在Lambda表达式中使用了某一个局部变量,那么这个局部变量的值在Lambda表达式之外,不可以被改变,因为默认将其定义成final常量。但全局变量变量没有这方面的限制。
示例:

@FunctionalInterface
public interface Printer {
	void setTime();
}
public class Tester {

	public static void main(String[] args) {
		int time = 10;
		Printer p = () -> System.out.println(time);//这里出错了,因为下一行对time进行修改
		time = 15;//这里的值不能改变,会导致上一行出错

	}
}

基本概括了Lambda表达式的所有用法,不足之处,请谅解,谢谢!

到此这篇关于简单易懂的java8新特性之lambda表达式知识总结的文章就介绍到这了,更多相关java lambda表达式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解Java8中的Lambda表达式

    Lambda是什么 Lambda表达式,也可称为闭包,是java8的新特性,作用是取代大部分内部类,优化java代码结构,让代码变得更加简洁紧凑. Lambda的基本语法 (expression)->expression 或 (expression)->{statements;} Lambda最重要特点 用()->{}代码块替代匿名内部类 //(param)->expression;//(param)->statment;//(param)->{statments};/

  • Java8新特性:Lambda表达式之方法引用详解

    1.方法引用简述 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法.方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文.计算时,方法引用会创建函数式接口的一个实例. 当Lambda表达式中只是执行一个方法调用时,不用Lambda表达式,直接通过方法引用的形式可读性更高一些.方法引用是一种更简洁易懂的Lambda表达式. Lambda表达式全文详情地址:http://blog.csdn.net/sun_promise/article/details/

  • Java8的Lambda表达式你真的会吗

    理解Lambda Lambda表达式可以是一段可以传递的代码,它的核心思想是将面向对象中的传递数据变成传递行为,也就是行为参数化,将不同的行为作为参数传入方法. 随着函数式编程思想的引进,Lambda表达式让可以用更加简洁流畅的代码来代替之前冗余的Java代码. 口说无凭,直接上个例子吧.在Java8之前,关于线程代码是这样的: class Task implements Runnable{ @Override public void run() { System.out.println("Ja

  • java8 forEach结合Lambda表达式遍历 List操作

    我就废话不多说了,大家还是直接看代码吧~ @Test void testJava8ForeachMap() { Map<String, Integer> items = new HashMap<>(); items.put("A", 10); items.put("B", 20); items.put("C", 30); items.put("D", 40); items.put("E&quo

  • Java8中Lambda表达式使用和Stream API详解

    前言 Java8 的新特性:Lambda表达式.强大的 Stream API.全新时间日期 API.ConcurrentHashMap.MetaSpace.总得来说,Java8 的新特性使 Java 的运行速度更快.代码更少.便于并行.最大化减少空指针异常. 0x00. 前置数据 private List<People> peoples = null; @BeforeEach void before () { peoples = new ArrayList<>(); peoples

  • Java8 用Lambda表达式给List集合排序的实现

    Lambda用到了JDK8自带的一个函数式接口Comparator<T>. 准备一个Apple类 public class Apple { private int weight; private String color; public Apple(){} public Apple(int weight) { this.weight = weight; } public Apple(int weight, String color) { this.weight = weight; this.c

  • java8学习教程之lambda表达式的使用方法

    前言 我们在 上一篇文章 中介绍了 lambda 表达式的语法,引入了 lambda 表达式的使用场景,以及使用 lambda 表达式的好处.我们将在这篇文章中,已实例讲解如何定义和使用 lambda 表达式,以及与其它语言相比,lambda 表达式在 Java 中的特殊规范. 使用匿名内部类的例子 首先明确一点,在 Java8 出现之前,lambda 表达式能够做到的,使用内部类也能做到,lambda 表达式只是简化了编程. 下面的例子是从列表中根据条件挑选出读者. 定义 TantanitRe

  • Java8新特性之Lambda表达式的使用

    1. lambda表达式介绍 lambda表达式是Java8提供的新特性之一,也可以称之为闭包:它支持Java能够进行简单的函数式编程,也就是说可以把一个匿名函数作为一个方法的参数进行传递:其格式分为三部分,第一部分为入参列表,第二部由->固定组成,第三部分为方法体: public class LambdaTest { public static void main(String[] args) { // 使用lambda表达式创建线程 Thread thread = new Thread(()

  • Java8 lambda表达式2种常用方法代码解析

    与python不一样,python lambda是定义匿名函数,而在java8中lambda是匿名内部类 例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runnable实现方法,需要4行代码,而使用lambda表达式只需要一行代码.我们在这里做了什么呢?那就是用() -> {}代码块替代了整个匿名类. // Java 8之前: new Thread(ne

  • JAVA8 lambda表达式权威教程

    Java 8新特性----Stream流 jdk8是Java 语言开发的一个主要版本,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等等.今天就重点介绍一个非常重要得特性之一 lambda表达式 一:什么是 Stream? Stream(流)是一个来自数据源的元素队列并支持聚合操作 Java中的Stream并不会存储元素,而是按需计算. 数据源 流的来源. 可以是集合,数组,I/O channel, 产生器generator 等. 聚合操作 类似

  • Java8与Scala中的Lambda表达式深入讲解

    前言 最近几年Lambda表达式风靡于编程界.很多现代编程语言都把它作为函数式编程的基本组成部分.基于JVM的编程语言如Scala.Groovy及Clojure把它作为关键部分集成在语言中.而如今,(最终)Java 8也加入了这个有趣的行列. Java8 终于要支持Lambda表达式!自2009年以来Lambda表达式已经在Lambda项目中被支持.在那时候,Lambda表达式仍被称为Java闭包.在我们进入一些代码示例以前,先来解释下为什么Lambda表达式在Java程序员中广受欢迎. 1.为

  • Java8 Lambda表达式模板方法实现解析

    Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解. Java1.5引入了注解,当前许多java框架中大量使用注解,如Hibernate.Jersey.Spring.注解作为程序的元数据嵌入到程序当中.注解可以被一些解析工具或者是编译工具进行解析.我们也可以声明注解在编译过程或执行时产生作用. 在使用注解之前,程序源数据只是通过java注释和javadoc,但是注解提供的功能要远远超

随机推荐