温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java8的匿名函数lambda表达式实例分析

发布时间:2022-02-24 10:40:42 来源:亿速云 阅读:159 作者:iii 栏目:开发技术

这篇“java8的匿名函数lambda表达式实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“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表达式实例分析”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI