包头索易网站建设,做外贸好还是跨境电商好,用单位的服务器做网站,做医院网站公司吗一 Lambda表达式的简介
Lambda表达式#xff08;闭包#xff09;#xff1a;java8的新特性#xff0c;lambda运行将函数作为一个方法的参数#xff0c;也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。
Lambda表达式的使用场景#xff1a;用以简…一 Lambda表达式的简介
Lambda表达式闭包java8的新特性lambda运行将函数作为一个方法的参数也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。
Lambda表达式的使用场景用以简化接口实现。
关于接口实现可以有很多种方式来实现。例如设计接口的实现类、使用匿名内部类。 但是lambda表达式比这两种方式都简单
package test;/*** author: Mercury* Date: 2022/3/20* Time: 17:48* Description:Lambda表达式* Version:1.0*/
public class Test04 {public static void main(String[] args) {//使用lambda表达式实现接口Test test () - {System.out.println(test);};test.test();}
}interface Test{public void test();
}二 Lambda表达式对接口的要求
虽然说lambda表达式可以在⼀定程度上简化接口的实现。但是并不是所有的接口都可以使用lambda表达式来简洁实现的。
lambda表达式毕竟只是⼀个匿名方法。当实现的接口中的方法过多或者多少的时候lambda表达式都是不适用的。
lambda表达式只能实现函数式接口
2.1 函数式接口
如果说⼀个接口中要求实现类必须实现的抽象方法有且只有⼀个这样的接口就是函数式接口。
//有且只有一个实现类必须要实现的抽象方法所以是函数式接口
interface Test{public void test();
}2.2 FunctionalInterface
是⼀个注解用在接口之前判断这个接口是否是⼀个函数式接口。 如果是函数式接口没有任何问题。如果不是函数式接口则会报错。功能类似于 Override。 代码如下示例
FunctionalInterface
interface Test{public void test();
}三 Lambda表达式的语法
3.1 Lambda表达式的基础语法
lambda表达式其实本质来讲就是⼀个匿名函数。因此在写lambda表达式的时候不需要关心方法名是什么。
实际上我们在写lambda表达式的时候也不需要关心返回值类型。
我们在写lambda表达式的时候只需要关注两部分内容即可参数列表和方法体
lambda表达式的基础语法
(参数1,参数2,…) - {
方法体
};参数部分方法的参数列表要求和实现的接口中的方法参数部分⼀致包括参数的数量和类型。
方法体部分 方法的实现部分如果接口中定义的方法有返回值则在实现的时候注意返回值的返回。
- : 分隔参数部分和方法体部分。
package test;/*** author: Mercury* Date: 2022/3/20* Time: 17:48* Description:Lambda表达式* Version:1.0*/
public class Test04 {public static void main(String[] args) {//使用lambda表达式实现接口//无参
// Test test () - {
// System.out.println(test);
// };//有参
// Test test (name,age) - {
// System.out.println(nameage岁了);
// };
// test.test(小新,18);//有参返回值Test test (name,age) - {System.out.println(nameage岁了);return age 1;};int age test.test(小新,18);System.out.println(age);}
}//无参
//interface Test{
// public void test();
//}//有参 无返回值
//interface Test{
// public void test(String name,int age);
//}//有参 有返回值
interface Test{public int test(String name,int age);
}3.2 Lambda表达式的语法进阶
参数部分的精简
参数的类型 由于在接口的方法中已经定义了每⼀个参数的类型是什么。而且在使用lambda表达式实现接口的时候必须要保证参数的数量和类 型需要和接口中的方法保持⼀致。因此此时lambda表达式中的参数的类型可以省略不写。
注意点如果需要省略参数的类型要保证要省略 每⼀个参数的类型都必须省略不写。绝对不能出现有的参数类型省略了有的参数类型没有省略。
//有参返回值
Test test (name,age) - {System.out.println(nameage岁了);return age 1;
};
int age test.test(小新,18);
System.out.println(age);参数的小括号
如果方法的参数列表中的参数数量 有且只有⼀个此时参数列表的小括号是可以省略不写的。
注意事项
只有当参数的数量是⼀个的时候 多了、少了都不能省略。省略掉小括号的同时 必须要省略参数的类型
方法体部分的精简 当⼀个方法体中的逻辑有且只有⼀句的情况下⼤括号可以省略
Test test name - System.out.println(nametest);test.test(小新);return的精简
如果⼀个方法中唯⼀的⼀条语句是⼀个返回语句 此时在省略掉大括号的同时 也必须省略掉return。
Test test (a,b) - ab;四 函数引用
lambda表达式是为了简化接口的实现的。在lambda表达式中不应该出现比较复杂的逻辑。如果在lambda表达式中出现了过于复杂的逻辑会对程序的可读性造成非常大的影响。如果在lambda表达式中需要处理的逻辑比较复杂⼀般情况会单独的写⼀个方法。在lambda表达式中直接引用这个方法即可。
函数引用引用⼀个已经存在的方法使其替代lambda表达式完成接口的实现
4.1 静态方法的引用
语法类::静态方法
在引用的方法后面不要添加小括号。引用的这个方法参数数量、类型和返回值必须要跟接口中定义的⼀致
package test;/*** author: Mercury* Date: 2022/3/20* Time: 18:17* Description:lambda表达式静态方法引用* Version:1.0*/
public class Test05 {public static void main(String[] args) {//实现多个参数一个返回值的接口//对一个静态方法的引用语法类::静态方法Test1 test1 Calculator::calculate;System.out.println(test1.test(4,5));}
}class Calculator{public static int calculate(int a,int b ){// 稍微复杂的逻辑计算a和b的差值的绝对值if (a b) {return a - b;}return b - a;}
}interface Test1{int test(int a,int b);
}4.2 非静态方法的引用
语法类::静态方法 注意事项
在引用的方法后面不要添加小括号。引用的这个方法参数数量、类型和返回值必须要跟接口中定义的⼀致
package test;/*** author: Mercury* Date: 2022/3/21* Time: 8:14* Description:lambda表达式对非静态方法的引用* Version:1.0*/
public class Test06 {public static void main(String[] args) {//对非静态方法的引用需要使用对象来完成Test2 test2 new Calculator()::calculate;System.out.println(test2.calculate(2, 3));}private static class Calculator{public int calculate(int a, int b) {return a b ? a - b : b - a;}}
}
interface Test2{int calculate(int a,int b);
}4.3.构造方法的引用
如果某⼀个函数式接口中定义的方法仅仅是为了得到⼀个类的对象。此时我们就可以使用构造方法的引用简化这个方法的实现。
语法类名::new 注意事项可以通过接口中的方法的参数 区分引用不同的构造方法。
package com.cq.test;/*** author: Mercury* Date: 2022/4/27* Time: 10:31* Description:lambda构造方法的引用* Version:1.0*/
public class Test {private static class Dog{String name;int age;//无参构造public Dog(){System.out.println(一个Dog对象通过无参构造被实例化了);}//有参构造public Dog(String name,int age){System.out.println(一个Dog对象通过有参构造被实例化了);this.name name;this.age age;}}//定义一个函数式接口,用以获取无参的对象FunctionalInterfaceprivate interface GetDog{//若此方法仅仅是为了获得一个Dog对象而且通过无参构造去获取一个Dog对象作为返回值Dog test();}//定义一个函数式接口,用以获取有参的对象FunctionalInterfaceprivate interface GetDogWithParameter{//若此方法仅仅是为了获得一个Dog对象而且通过有参构造去获取一个Dog对象作为返回值Dog test(String name,int age);}// 测试public static void main(String[] args) {//lambda表达式实现接口GetDog lm Dog::new; //引用到Dog类中的无参构造方法获取到一个Dog对象Dog dog lm.test();System.out.println(修狗的名字dog.name 修狗的年龄dog.age); //修狗的名字null 修狗的年龄0GetDogWithParameter lm2 Dog::new;//引用到Dog类中的有参构造来获取一个Dog对象Dog dog1 lm2.test(萨摩耶,2);System.out.println(修狗的名字dog1.name 修狗的年龄dog1.age);//修狗的名字萨摩耶 修狗的年龄2}
}五 Lambda表达式需要注意的问题
这⾥类似于局部内部类、匿名内部类依然存在闭包的问题。
如果在lambda表达式中使用到了局部变量那么这个局部变量会被隐式的声明为 final。是⼀个常量不能修改值。