Lambda表达式

一、函数式接口

函数式接口(functional interface 也叫功能性接口,其实是同一个东西)。简单来说,函数式接口是只包含一个方法的接口。比如Java标准库中的java.lang.Runnable和 java.util.Comparator都是典型的函数式接口。
java 8提供 @FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准(即只包含一个方法的接口),虚拟机会自动判断, 但 最好在接口上使用注解@FunctionalInterface进行声明,以免团队的其他人员错误地往接口中添加新的方法。

Java中的lambda无法单独出现,它需要一个函数式接口来盛放,lambda表达式方法体其实就是函数接口的实现.

下面的接口就是一个函数式接口

package com.yztcedu.lambdademo_01;

@FunctionalInterface //添加此注解后,接口中只能有一个抽象方法。
public interface A {
	void call();

}

二、lambda语法

包含三部分:
1、一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
2、一个箭头符号:->
3、方法体,可以是表达式和代码块。

(parameters) -> expression 或者 (parameters) -> { statements; }

通过下面的代码可以看到lambda表达式设计的代码更简洁,而且可读性更好。

package com.yztcedu.lambdademo_01;

public class Demo1 {
	public static void main(String[] args) {
		runThreadByLambda();
		runThreadByInnerClass();
	}

	public static void runThreadByLambda() {
		/*
		 Runnable就是一个函数式接口:他只有一个方法run()方法。
		 1、因为run()方法没有参数,所以   ->前面的()中不需要声明形参
		 2、run返回的是void,所以不需要return。
		 3、->后面写的代码其实就是定义在run方法内的代码。因为此处代码只有一行,所以{}也可以省略。如果此处多与一行,则无法省略。
		 */
		Runnable runnable = () -> System.out.println("这个是用拉姆达实现的线程");
		new Thread(runnable).start();
	}

	public static void runThreadByInnerClass() {
		Runnable runnable = new Runnable() {

			@Override
			public void run() {
				System.out.println("这个是用内部类实现的线程");

			}
		};
		new Thread(runnable).start();
	}
}

三、方法引用

其实是lambda表达式的一种简化写法。所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是"::",右边是相应的方法名。如下所示:

ObjectReference::methodName

一般方法的引用格式:

  1. 如果是静态方法,则是ClassName::methodName。如 Object ::equals
  2. 如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;
  3. 构造函数.则是ClassName::new
package com.yztcedu.lambdademo_01;

public class Demo2 {
	public static void main(String[] args) {
		/*
		 * 方法引用
		 */
		Runnable runnable = Demo2::run;//此处本应该是函数式接口的匿名内部类的,表达式Demo2::run,把下面run方法的实现,放到了函数式接口的匿名内部类的run方法中
		new Thread(runnable).start();
	}
	
	
	public static void run(){
		System.out.println("方法引用的代码...");
	}

}

可以看出,run方法就是lambda表达式的实现,这样的好处就是,如果你觉得lambda的方法体会很长,影响代码可读性,方法引用就是个解决办法

四、默认方法和static方法---接口改进

简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法。只需在方法名前面加个default关键字即可。

package com.yztcedu.lambdademo_01;

@FunctionalInterface
public interface A {
	void call();

	default void fun() {
		System.out.println("我是接口的默认方法1中的代码");
	}

	default void fun2() {
		System.out.println("我是接口的默认方法2中的代码");
	}

}

为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口 添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了使接口没有引入与现有的实现不兼容扩展。

Java8中接口引入了defualt,static两种方法提供默认实现,彻底打破了接口不能有默认实现的规定:

static

让接口类似于工具类,提供一些静态方法

static方法不会被子类继承

defualt

给接口加入了默认方法实现

defualt方法会被子类继承,defualt方法的重要运用场景,接口需要新加一个方法,可以帮助我们向后兼容的同时,不断演进,同时我们应该发现这样一来Java也相当于有了部分多重继承的能力。

 
posted @ 2021-06-03 15:24  活在当下~W  阅读(69)  评论(0)    收藏  举报