Java8新特性1——函數(shù)式接口&lambda表達式
注:以下內(nèi)容基于Java 8,所有代碼都已在Java 8環(huán)境下測試通過
目錄:
- Java8新特性1——函數(shù)式接口&lambda表達式
- Java8新特性2——方法引用
- Java8新特性3——Stream
1. 函數(shù)式接口
如果在一個接口中,有且只有一個抽象方法,則該接口被稱為函數(shù)式接口。如:
interface Test {
void test();
}
注:
可以在接口前使用 @FunctionalInterface
注解,判斷這個接口是否是?個函數(shù)式接口。如:
@FunctionalInterface
interface Test1 {//有且僅有一個抽象方法,是函數(shù)式接口
void test();
}
@FunctionalInterface
interface Test2 {//有且僅有一個抽象方法,是函數(shù)式接口
void test();
default void f() {
}
}
@FunctionalInterface
interface Test3 {//沒有抽象方法,不是函數(shù)式接口,編譯器報錯
}
@FunctionalInterface
interface Test4 {//有多個抽象方法,不是函數(shù)式接口,編譯器報錯
void test1();
void test2();
}
2. lambda表達式
2.1 lambda表達式作用
lambda表達式是一個匿名函數(shù),用于簡化函數(shù)式接口的實現(xiàn)。
在Java中,接口不能實例化,但接口對象可以指向?qū)崿F(xiàn)類對象。當(dāng)沒有實現(xiàn)類對象時,可以通過匿名類的方式,如:
public class Main {
public static void main(String[] args) {
Test test = new Test() {
@Override
public void f() {
System.out.println("使用匿名函數(shù)的方式實現(xiàn)了函數(shù)式接口");
}
};
test.f();
}
}
@FunctionalInterface
interface Test {
void f();
}
使用匿名類的方式代碼不是很簡潔,因此引入了lambda表達式,如:
public class Main {
public static void main(String[] args) {
Test test = () -> System.out.println("使用lambda表達式的方式實現(xiàn)了函數(shù)式接口");
test.f();
}
}
@FunctionalInterface
interface Test {
void f();
}
在使用lambda表達式之后,代碼變得簡潔了很多,因此可以說lambda表達式是和函數(shù)式接口相輔相成的。在上面的代碼中,lambda表達式實際做了以下三個工作:
-
自動實現(xiàn)接口
Test test = new Test();
-
將
->
前的參數(shù)自動添加到抽象函數(shù)里面(上面代碼中抽象函數(shù)沒有參數(shù))void f();
-
將
->
后的語句作為抽象函數(shù)的方法體void f(){ System.out.println("使用lambda表達式的方式實現(xiàn)了函數(shù)式接口"); }
2.2 lambda表達式語法格式
lambda表達式的格式如下:
(參數(shù)1, 參數(shù)2, ……) -> {
方法體;
}
其中:
- 參數(shù)要求和函數(shù)式接口中抽象方法的參數(shù)一致(包括數(shù)量和類型以及順序)
- 如果函數(shù)式接口中抽象方法有返回值,則實現(xiàn)的時候也需要返回值
public class Main {
public static void main(String[] args) {
Test test = (int x, int y) -> {//參數(shù)、返回值與函數(shù)式接口中抽象方法一致
return x + y;
};
test.add(1, 2);
}
}
@FunctionalInterface
interface Test {
int add(int x, int y);
}
2.3 lambda表達式的精簡
-
參數(shù)精簡
- 參數(shù)類型可以省略,若省略一個類型參數(shù),則所有的類型參數(shù)都要省略
- 若只有一個參數(shù),則小括號可以省略
- 若參數(shù)為0或者多于1個,則小括號不可以省略
-
方法體精簡
- 若方法體中只有一行代碼,則花括號可以省略
- 若方法體中只有一行代碼且是return語句,則在省略大括號的時候還需要去掉return關(guān)鍵字
- 若方法體中有多行代碼或者使用了return語句,則大括號不可以省略
public class Main { public static void main(String[] args) { //只有一個參數(shù),省略了小括號 //只有一條return語句,省略了花括號即return關(guān)鍵字 Test test = x -> Math.exp(x); test.exp(1); } } @FunctionalInterface interface Test { double exp(double x); }
2.4 變量作用域
- lambda表達式只可以訪問外部變量,但不能修改外部變量
- lambda表達式訪問的外部變量一般都是聲明為 final 的,但也可以不用聲明為 final ,但該變量在聲明后不能被修改
- lambda表達式中不允許聲明一個與局部變量同名的參數(shù)或局部變量
public class Main { static final int a = 0; public static void main(String[] args) { final int num1 = 10; int num2 = 20; //num2 = 40; //聲明后不能被修改 Test test1 = x -> { System.out.println(num1);//可以訪問外部被聲明為 final 的變量 System.out.println(num2);//可以訪問外部的普通變量 //num1 = 20;//只能訪問,不能修改 //num2 = 20;//只能訪問,不能修改 //int num1 = 20;//不允許聲明一個與局部變量同名的局部變量 return Math.exp(x); }; //num2 = 40; //聲明后不能被修改 test1.exp(1); //不允許聲明一個與局部變量同名的參數(shù) //Test test2 = num1 -> Math.exp(num1); } } @FunctionalInterface interface Test { double exp(double x); }
3. 四大函數(shù)式接口
為了讓開發(fā)者高效地使用函數(shù)式接口,Java 8 在 java.util.function
包下提供了許多函數(shù)式接口,以下四種是最為常見的:
接口原型 | 抽象方法 | 備注 |
---|---|---|
Consumer< T > | accept(T t) | 消費型接口 |
Supplier< T > | T get() | 供給型接口 |
Function<T, R> | R apply(T t) | 函數(shù)型接口 |
Predicate< T > | boolean test(T t) | 斷言型接口 |
3.1 Consumer< T >:消費型接口
該接口只接收輸入?yún)?shù)但不輸出返回值,消費對象,只進不出。
-
接口原型:
@FunctionalInterface public interface Consumer<T> { void accept(T t); }
-
使用示例:
import java.util.function.Consumer; public class Main { public static void main(String[] args) { Consumer<Integer> acc = (t) -> System.out.println(t);//實現(xiàn) Consumer 接口 acc.accept(10); } }
3.2 Supplier< T >:供給型接口
該接口只輸出返回值但不接收輸入?yún)?shù),生成對象,只出不進。
-
接口原型:
public interface Supplier<T> { T get(); }
-
使用示例:
import java.util.function.Supplier; public class Main { public static void main(String[] args) { Supplier<Integer> sup = () -> 10;//實現(xiàn) Supplier 接口 System.out.println(sup.get()); } }
3.3 Function<T, R>:函數(shù)型接口
該接口既接收輸入?yún)?shù)又輸出返回值,用于指定特定功能,有進有出。
-
接口原型:
@FunctionalInterface public interface Function<T, R> { R apply(T t); }
-
使用示例:
import java.util.function.Function; public class Main { public static void main(String[] args) { Function<Integer, String> fun = (x) -> {//實現(xiàn) Function 接口 String out = "輸入的整數(shù)是" + x; return out; }; System.out.println(fun.apply(10)); } }
3.4 Predicate< T >:斷言型接口
該接口既接收輸入?yún)?shù)又輸出返回值,且返回值只能是布爾值,用于條件判斷,有進有出。
-
函數(shù)原型:文章來源:http://www.zghlxwxcb.cn/news/detail-693574.html
public interface Predicate<T> { boolean test(T t); }
-
使用示例:文章來源地址http://www.zghlxwxcb.cn/news/detail-693574.html
import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<Integer> pre = (x) -> x % 2 == 0;//實現(xiàn) Predicate 接口 int a = 10; if (pre.test(10)) { System.out.println(a + "是偶數(shù)"); } else { System.out.println(a + "是奇數(shù)"); } } }
到了這里,關(guān)于Java8新特性1——函數(shù)式接口&lambda表達式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!