简单易懂的java8新特性之lambda表达式知识总结
作者:TS六道轮回 发布时间:2023-04-14 23:44:42
一、概念
从本质上来说,它就是一个匿名函数,可以用来直接实现接口中的方法,从而简化代码。但是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表达式的所有用法,不足之处,请谅解,谢谢!
来源:https://blog.csdn.net/hongyinanhai00/article/details/115935919


猜你喜欢
- 最近一个项目中,需要用到Java的websocket新特性,于是就学了一下,感觉这技术还挺好玩的,瞬间知道网页上面的那些在线客服是怎么做的了
- 本文实例讲述了C#从画刷创建画笔的方法。分享给大家供大家参考。具体实现方法如下:using System;using System.Coll
- 线程池的好处可以实现线程的复用,避免重新创建线程和销毁线程。创建线程和销毁线程对CPU的开销是很大的。可以限制最大可创建的线程数,可根据自己
- 本文实例为大家分享了Android实现类似微信视频接听的具体代码,供大家参考,具体内容如下1、背景需求:业务需要接入视频审核功能,在PC 端
- 两种情况setState() 能在 build() 中直接调用吗?答案是能也不能。来看一段简单的代码:import 'package
- 本文实例为大家分享了Android霓虹闪烁文字效果的具体代码,供大家参考,具体内容如下package com.example.apple.s
- 一、ListView该组件是android中最常用的一个UI组件,用于实现在屏幕上显示多个内容,以便于我们用手指来回翻转。先在layout中
- IO流基本概念IO流用来处理设备之间的数据传输Java对数据的操作是通过流的方式Java用于操作流的对象都是在IO包上流按操作数
- 目录1. 新建产品,在官网新建产品2. 获取app id,点击产品设置,拿到App ID3. 集成SDK,在Android项目的 app/b
- Android使用RecyclerView1. 什么是RecyclerViewRecyclerView 是 Android-support-
- 本文将是JVM 性能优化系列的第二篇文章(第一篇:传送门),Java 编译器将是本文讨论的核心内容。本文中,作者(Eva Andreasso
- Monkeyrunner 常用按键 &nbs
- 一、PointCut接口/* * Copyright 2002-2012 the original author or authors. *
- 之前文章介绍过了Fluent基本框架等,其中有几个重要的方法用到了IQuery和IUpdate对象。 这2个对象是FluentMybatis
- 前言在我的申请下,公司终于购买了一台基于Android12.0的手机,然后我就开心的拿去安装测试了,发现程序崩溃了,于是我这里就写下来,An
- 本文实例为大家分享了Unity实现虚拟键盘的具体代码,供大家参考,具体内容如下这是一个网上找的插件,自己改了点东西,方便使用在项目中。暂时不
- 在Android开发中很多时候会遇到一屏显示不下所有内容的现象,那大家也知道这个时候肯定会想到用scrollview来进行滚屏显示。这个时候
- 本文实例为大家分享了Android自定义View实现拖动自动吸边的具体代码,供大家参考,具体内容如下自定义View,一是为了满足设计需求,二
- 前言本文介绍的是Android如何实现数字跳动效果的TextView,主要运用了DancingNumberView,DancingNumbe
- 前言小小知识,不值一提,了解了也不能让你提高身价,但是不了解你就是比别人少知道点!事儿就是这么个事儿,直接正题吧! 直接看代码演示优先级当方