Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
ambda 表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
以下是lambda表达式的重要特征:
- **可选参数类型声明:**不需要声明参数类型,编译器可以统一识别参数值。
- **可选的参数圆括号:**一个参数无需定义圆括号,但多个参数需要定义圆括号。
- **可选的大括号:**如果主体包含了一个语句,就不需要使用大括号。
- **可选的返回关键字:**如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
对接口的实现
Lambda 规定只能实现函数式接口,即接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法
**@FunctionalInterface
:**修饰函数式接口的,要求接口中的抽象方法只有一个,不是函数式接口会报错。 这个注解往往会和 lambda 表达式一起出现。
default
, 接口中被 default
修饰的方法不是必须被实现的方法,可以不实现,所以不影响 Lambda 表达式的使用。
接口默认重写 java.lang.Object
,所以如果接口显示声明覆盖了 Object 中方法,那么也不算抽象方法。
/**多参数无返回*/
@FunctionalInterface
public interface NoReturnMultiParam {
void method(int a, int b);
}
/**无参无返回值*/
@FunctionalInterface
public interface NoReturnNoParam {
void method();
}
/**一个参数无返回*/
@FunctionalInterface
public interface NoReturnOneParam {
void method(int a);
}
/**多个参数有返回值*/
@FunctionalInterface
public interface ReturnMultiParam {
int method(int a, int b);
}
/*** 无参有返回*/
@FunctionalInterface
public interface ReturnNoParam {
int method();
}
/**一个参数有返回值*/
@FunctionalInterface
public interface ReturnOneParam {
int method(int a);
}
//无参无返回
NoReturnNoParam noReturnNoParam = () -> System.out.println("NoReturnNoParam");
noReturnNoParam.method();
//一个参数无返回
NoReturnOneParam noReturnOneParam = a -> System.out.println("NoReturnOneParam param:" + a);
noReturnOneParam.method(6);
//多个参数无返回
NoReturnMultiParam noReturnMultiParam = (a, b) -> System.out.println("NoReturnMultiParam param:" + "{" + a +"," + + b +"}");
noReturnMultiParam.method(6, 8);
//无参有返回值
ReturnNoParam returnNoParam = () -> {
System.out.print("ReturnNoParam");
return 1;
};
int res = returnNoParam.method();
System.out.println("return:" + res);
//一个参数有返回值
ReturnOneParam returnOneParam = a -> {
System.out.println("ReturnOneParam param:" + a);
return 1;
};
int res2 = returnOneParam.method(6);
System.out.println("return:" + res2);
//多个参数有返回值
ReturnMultiParam returnMultiParam = (a, b) -> {
System.out.println("ReturnMultiParam param:" + "{" + a + "," + b +"}");
return 1;
};
int res3 = returnMultiParam.method(6, 8);
System.out.println("return:" + res3);
方法引用
方法的实现已经存在,lambda表达式去引用方法
接口要实现的方法参数必须与要引用的方法一致
普通方法与静态方法
简写:
- 对象::方法名
- 类名::静态方法
public class Exe1 {
public static void main(String[] args) {
//方法1
//相当于lambda表达式实现方法的调用
ReturnOneParam lambda1 = a -> doubleNum(a);
System.out.println(lambda1.method(3));
//方法2
//lambda2 引用了已经实现的 doubleNum 方法
ReturnOneParam lambda2 = Exe1::doubleNum;
System.out.println(lambda2.method(3));
Exe1 exe = new Exe1();
//方法3
//lambda4 引用了已经实现的 addTwo 方法
ReturnOneParam lambda4 = exe::addTwo;
System.out.println(lambda4.method(2));
}
/**
* 要求
* 1.参数数量和类型要与接口中定义的一致
* 2.返回值类型要与接口中定义的一致
*/
public static int doubleNum(int a) {
return a * 2;
}
public int addTwo(int a) {
return a + 2;
}
}
构造方法
简写:
类名::new
interface ItemCreatorBlankConstruct {
Item getItem();
}
interface ItemCreatorParamContruct {
Item getItem(int id, String name, double price);
}
public class Exe2 {
public static void main(String[] args) {
//方法1
//非简写
ItemCreatorBlankConstruct creator = () -> new Item();
Item item = creator.getItem();
//方法2
ItemCreatorBlankConstruct creator2 = Item::new;
Item item2 = creator2.getItem();
ItemCreatorParamContruct creator3 = Item::new;
Item item3 = creator3.getItem(112, "鼠标", 135.99);
}
}
对象方法的特殊引用
函数式接口的实现是实例方法,函数式接口的第一个参数作为调用方法的实例,后面的参数全部传给该实例方法作为参数。
// 3 类::实例方法 (1)Lambda中只调用一个方法 (2)一个参数作为调用者,其它参数还作为参数
Comparator<String> comparator1 = o -> o.a();
Comparator<String> comparator2 = O::a;
Comparator<String> comparator3 = (o1, o2) -> o1.compareTo(o2);
Comparator<String> comparator4 = String::compareTo;
线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("test");
}
});
t1.start();
Thread t2 = new Thread(()->{
print.printNum();
});
t2.start();
new Thread(()-> {
print.printNum();
}).start();
集合
java8中提供了许多函数式接口实现对集合的操作
闭包
-
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
-
lambda 表达式引用不是final 的外层局部变量,编译时,会自动加上final,后面的代码修改变量会报错。
-
Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。