目錄
前言:
Oracle 公司於 2014 年 3 月 18 日發佈 Java 8,JDK8新特性函數式編程,
Lambda 表達式 − Lambda 允許把函數作爲一個方法的參數(函數作爲參數傳遞到方法中)。使用 Lambda 表達式可以使代碼變的更加簡潔緊湊。Lambda表達式就是用來簡化創建匿名內部接口對象的。
函數式接口 有函數式接口才能使用Lambda表達式。
默認(和靜態)方法 針對接口的,可以有自己的實現方法。
函數式接口
@FunctionalInterface
interface TestInterface {
void sop(String message);
}
函數式接口要在接口上聲明標籤:
@FunctionalInterface
當然也可以不聲明此標籤,聲明此標籤的目的是爲了註明是函數式接口,在IDE上能自動檢查此類是否符合函數式接口規則。
函數式接口規則:
- 接口必須一定只能有一個抽象方法。(記住)。除了Object方法
- 除了接口能包含靜態方法和默認方法。(後面會講)
在瞭解完函數式接口,接下來就是如何使用Lambda表達式
Lambda表達式
Lambda表達式就是用來簡化創建內部接口對象的。
語法:
(聲明參數) -> {實現代碼}
- () 可選圓括號:情況一:無參方法,直接 () 表示。情況二:只有一個參數,可以忽略 ()。情況三:多個參數,必須用()圓括號,裏面用 , 英文逗號分開。
- -> 減 + 大於號:參數在左,實現在右。
- {} 可選大括號:情況一:主體只有一條語句,及只有一個 ; 分號的實現,可以忽略 {}。情況二:有返回值方法,並且主體只有一條返回值語句,及 ; 分號只有一個,可以忽略 {} 。情況三:有返回值的方法,一定要使用 {},則必須顯示聲明return。
- () 參數類型可選顯示化:可直接忽略參數類型,直接聲明變量名。如果顯示聲明參數類型必須配合 () 圓括號使用。
Lambda表達式示列代碼
package com.bin.demo;
@FunctionalInterface
interface NoValue {
void nv();
}
@FunctionalInterface
interface Value {
void v(int x, int y);
}
@FunctionalInterface
interface RValue {
String rv(String value);
}
public class Main {
public static void main(String[] args) {
//無參創建
NoValue nv = () -> System.out.println("雨煙");
// 聲明參數類型
Value v = (int x, int y) -> System.out.println("斌哥" + x + y);
//不聲明參數類型
Value v2 = (x, y) -> System.out.println("好想得到稱霸地球的力量" + x + y);
//大括號返回值
RValue rv = str -> {return "雷姆";};
//無大括號返回值
RValue rv2 = str -> "時崎狂三";
//自動推斷的參數類型,並使用函數式參數
sop(name -> name + "我想毀滅這個世界");
}
//常用於方法參數的 函數式參數傳遞
private static void sop(RValue r) {
System.out.println(r.rv("斌哥 sop -> "));
}
}
輸出:
斌哥 sop -> 我想毀滅這個世界
使用Lambda表達式注意
- 創建的接口對象畢竟是 匿名內部類對象,在使用外層變量時,外層變量同樣要final修飾。
- 聲明的參數名不允許相同。
如下示列會報錯:
package com.bin.demo;
@FunctionalInterface
interface Value {
void v(int x, int y);
}
public class Main {
public static void main(String[] args) {
//未使用final修飾,並且外層類變量名與函數式內部類變量名相同。報錯
int x = 1, y = 1;
Value v = (int x, int y) -> System.out.println(x + y);
Value v2 = (x, y) -> System.out.println(x + y);
//糾正
final int x = 1, y = 1;
Value v = (int a, int b) -> System.out.println(x + y);
Value v2 = (a, b) -> System.out.println(x + y);
}
}
接口默認(和靜態)方法
就是在接口中顯示聲明關鍵字default修飾符默認方法,讓接口有自己的實現方法。
interface Value {
default int to(int c, int b) {
return c + b;
}
static void sop() {
System.out.println("接口靜態方法");
}
}
interface Value2 {
default int to(int c, int b) {
return c - b;
}
}
接口默認方法重複問題解決
一個類實現了兩個接口,而兩個接口的默認方法是重複的(同名同參),這樣我們在創建這個類的對象時,該怎麼確定調用的是哪個默認方法呢?
這時候編譯器必須要求我們重寫不同接口的重名方法:
package com.bin.demo;
interface Value {
default int to(int c, int b) {
return c + b;
}
static void sop() {
System.out.println("接口靜態方法");
}
}
interface Value2 {
default int to(int c, int b) {
return c - b;
}
}
class Test implements Value, Value2 {
@Override
public int to(int c, int b) {
//允許使用 類名.super.方法() 的方式調用指定接口默認方法
int c1 = Value.super.to(c, b);
int c2 = Value2.super.to(c, b);
System.out.println(c1);
System.out.println(c2);
return (c1 + c2);
}
}
public class Main {
public static void main(String[] args) {
System.out.println(new Test().to(50, 20));
}
}
通過使用 類名.super.方法() 的方式調用指定接口默認方法