javaLambda表达式
/**
* Lambda表达式用于简化代码
* 函数式接口:只有一个抽象方法的接口,可以有其他默认方法
* Lambda表达式可用于简化匿名内部类的代码结构
*/
@FunctionalInterface
interface NoReturn0Parameter{
//包含没有返回值,没有参数的抽象方法的函数式接口
//在接口上方用注释@FunctionalInterface 来限制接口内只能有一个抽象方法,当有多个时报错
void method();
//抽象方法:返回值类型 方法名()
}
@FunctionalInterface
interface NR1P{
//无返回1参数
void method(int a);
}
@FunctionalInterface
interface NR2P{
//无返回2参
void method(int a,int b);
}
@FunctionalInterface
interface R0P{
//有返回值无参
int method();
}
@FunctionalInterface
interface R1P{
//有返回1参
int method(int a);
}
@FunctionalInterface
interface R2P{
//有返回2参
int method(int a,int b);
}
public class TestLambda1 {
public static void main(String[] args) {
NoReturn0Parameter noReturn0Parameter = new NoReturn0Parameter() {
//匿名内部类通常写法
@Override
public void method() {
System.out.println("TestLambda1.method");
}
};
NoReturn0Parameter noReturn0Parameter1 = ()->{
System.out.println("TestLambda1.main");
};
//Lambda表达式格式: (参数)->{方法体}
//无参所以用(),{}方法体不用写声明的部分(public void method),因为函数式接口必须只有一个抽象方法,所以lambda实现的就是这个方法,所以省略了声明
noReturn0Parameter1.method();
//noReturn0Parameter1是实现类对象,引用类型是NoReturn0Parameter接口,实现了方法后可正常调用
NR1P nr1P = (int a)->{
System.out.println(a);
};
nr1P.method(20);
NR2P nr2P = (int a,int b)->{
System.out.println(a+b);
};
nr2P.method(20,30);
R0P r0P = ()->{
System.out.println("TestLambda1.main");
return 10;
};
//有返回值则在方法体内写明
int c = r0P.method();
R1P r1P = (int a) -> {
System.out.println("TestLambda1.main");
return a;
};
R2P r2P = (int a, int b)->{
System.out.println("TestLambda1.main");
return a+b;
};
}
}
class TestLambda2{
public static void main(String[] args) {
//简写Lambda,()->{}是完整形式,代码可以再简化
NoReturn0Parameter noReturn0Parameter = ()-> System.out.println("TestLambda2.main");
//方法体{}只有一行代码时可以去掉{}
NR1P nr1P = a-> System.out.println(a);
//参数()只有一个参数时可以省略(),参数可以省略类型
NR2P nr2P = (a,b)-> System.out.println(a+b);
//只有在参数为一个时可以省略(),但可以省略类型
R0P r0P = ()->20;
//当方法体只有一句return 20 时将{}和return都省略
R1P r1P = a->{
System.out.println("TestLambda2.main");
return a;
};
//当方法体有多行代码时{}和return都不能省略
R2P r2P = (a,b)->a+b;
//将{return a+b}简写为a+b
//闭包问题
int x = 20;
NoReturn0Parameter noReturn0Parameter1 = new NoReturn0Parameter() {
@Override
public void method() {
System.out.println(x);
}
};
//匿名内部类为闭包的一种,在闭包中调用外部的变量,会将变量赋final属性,后续再对x进行更改的话内部类的x会报错,如果在内部类之前变量x就已经多次赋值了,在闭包中调用x会直接报错,lambda表达式简化匿名内部类代码,在表达式内调用外部变量同样会赋final属性
//x++;报错
}
}
class TestLambda3{
//在Lambda中引入其他方法
public static void print(int a){
System.out.println(a);
}
public int times(int a,int b){
return a*b;
}
public static void main(String[] args) {
NR1P nr1P = a->TestLambda3.print(a);
//使用已存在的方法来实现抽象方法
nr1P = TestLambda3::print;
//简写为 方法归属者::方法名
//要求引入的方法和抽象方法的参数列表和返回值类型必须一致,而因为参数和返回值一致所以将()参数和return都省略了,->goes to运算符也省略了,而print静态方法属于类TestLambda3,所以写为类名::方法名
R2P r2P = new TestLambda3()::times;
//times方法属于对象,所以引用时需要写为 对象::方法名
NR1P nr1P1 = System.out::println;
//将 a->System.out.println(a);简写 println是属于对象out的
R2P r2P1 = Integer::sum;
//将 (a,b)->a+b; 改写为调用Integer.sum(int a,int b)方法
//反过来说,将Integer.sum(int a,int b)方法的.换成:: 再去掉参数(int a,int b),写成Integer::sum
//使用Lambda表达式创建线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("通常的匿名内部类");
}
},"匿名内部类线程");
Thread t2 = new Thread(()->{
System.out.println("因为new Thread()构造器中声明了参数类型为Runnable,Lambda表达式将引用类型变量 Runnable xxx= 省略,只写表达式的部分");
System.out.println("Runnable接口内只有一个抽象方法run(),没有其他任何内容,即Runnable接口为函数式接口,适用Lambda");
});
}
}