Lambda是表達式,也可以成爲閉包,是java8的重要特性;
Lambda允許把函數作爲作爲一個方法的參數(函數作爲參數傳遞進方法中);
使用Lambda可以使代碼更整潔;
語法
方法一:(parameters)->expression
方法二:(parameters)->{expression;}
Lambda 表達式實例
// 1. 不需要參數,返回值爲 5
() -> 5
// 2. 接收一個參數(數字類型),返回其2倍的值
x -> 2 * x
// 3. 接受2個參數(數字),並返回他們的差值
(x, y) -> x – y
// 4. 接收2個int型整數,返回他們的和
(int x, int y) -> x + y
// 5. 接受一個 string 對象,並在控制檯打印,不返回任何值(看起來像是返回void)
(String s) -> System.out.print(s)
例子
public class LambdaTest {
public static void main(String[] args) {
LambdaTest test=new LambdaTest();
//聲明類型
MathOperation addition=(int a,int b)->a+b;
//不用聲明類型
MathOperation subtraction=(a,b)->a-b;
//大括號返回語句
MathOperation mutiplication=(int a,int b)->{return a*b;};
//沒有大括號及返回語句
MathOperation division=(int a,int b)->a/b;
System.out.println("10+5= "+test.operate(10, 5, addition));
System.out.println("10-5= "+test.operate(10, 5, subtraction));
System.out.println("10*5= "+test.operate(10, 5, mutiplication));
System.out.println("10/5= "+test.operate(10, 5, division));
//不用括號:
GreetingService service=message->System.out.println("hello:"+message);
//使用括號
GreetingService service2=(message)->System.out.println("你好:"+message);
service.sayMessage("tom");
service2.sayMessage("jim");
}
interface MathOperation{
int operation(int a,int b);
}
interface GreetingService{
void sayMessage(String message);
}
private int operate(int a,int b,MathOperation math) {
return math.operation(a, b);
}
}
10+5= 15
10-5= 5
10*5= 50
10/5= 2
hello:tom
你好:jim
變量作用域
lambda 表達式只能引用標記了 final 的外層局部變量,這就是說不能在 lambda 內部修改定義在域外的局部變量,否則會編譯錯誤。
public class LambdaTest2 {
final static int a=888;
public static void main(String[] args) {
LambdaTest2 test=new LambdaTest2();
//不用括號:
GreetingService service=message->System.out.println("hello:"+message+a);
//使用括號
GreetingService service2=(message)->System.out.println("你好:"+message+a);
service.sayMessage("tom");
service2.sayMessage("jim");
}
interface GreetingService{
void sayMessage(String message);
}
}
hello:tom888
你好:jim888
public class LambdaTestThree {
public static void main(String[] args) {
final int num=1;
Converter<Integer, String> s=(params)->System.out.println(String.valueOf(params+num));
s.conver(2);//輸出結果爲3
}
interface Converter<T1,T2>{
void conver(int i);
}
}
lambda 表達式的局部變量可以不用聲明爲 final,但是必須不可被後面的代碼修改(即隱性的具有 final 的語義
public class LambdaTestThree {
public static void main(String[] args) {
int num=1;
Converter<Integer, String> s=(params)->System.out.println(String.valueOf(params+num));
s.conver(2);//輸出結果爲3
num=5; //報錯信息:Local variable num defined in an enclosing scope must be final or effectively final
}
interface Converter<T1,T2>{
void conver(int i);
}
}
在 Lambda 表達式當中不允許聲明一個與局部變量同名的參數或者局部變量。
public class LambdaTestThree {
public static void main(String[] args) {
int p=1;
Converter<Integer, String> s=(p)->System.out.println(String.valueOf(p+p));
//Lambda expression's parameter params cannot redeclare another local variable defined in an enclosing scope.
s.conver(2);//輸出結果爲3
}
interface Converter<T1,T2>{
void conver(int i);
}
}
訪問對象字段與靜態變量
public class LambdaTestThree {
static int paramMeterNum;
int outNum;
public void test() {
int p=1;
Converter<Integer, String> s1=(sw)->{
System.out.println("s1 function!"+sw);
paramMeterNum=23;
System.out.println("paramMeterNum paramMeterNum is"+paramMeterNum);};
Converter<Integer, String> s2=(w2)->{
System.out.println("s2 function!"+w2);
outNum=3;
System.out.println("outNum paramMeterNum is"+outNum);
};
s1.conver(2);
s2.conver(33);
}
interface Converter<T1,T2>{
void conver(int i);
}
public static void main(String[] args) {
LambdaTestThree test1=new LambdaTestThree();
test1.test();
}
}
s1 function!2
paramMeterNum paramMeterNum is23
s2 function!33
outNum paramMeterNum is3
函數式接口:
Lambda表達式是如何在java的類型系統中表示的呢?每一個Lamdba表達式都對應一個類型,通常是接口類型。而“函數式接口”是指僅僅只包含一個抽象方法的接口,每一個該類型的lamdba表達式都會被匹配到這個抽象方法。
我們可以將lamdba表達式當做任意只包含一個抽象方法的接口類型,確保你的接口一定達到這個要求,你只需要在接口添加@FunctionalInterface 註解,編譯器如果發現你標註了這個註解的接口有多於一個抽象方法的時候會報錯的。
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted); // 123
如果沒有@FunctionalInterface這個也是對的
注: 大部分函數式接口都不用開發者們自己寫,Java8 中基本已經實現好了,這些接口都在 java.util.function 包裏。