深入理解Java8新特性之Lambda表達式的基本語法和自定義函數式接口
1.寫在前面
目前我們學習Java主要用到的應該就是Java8了,或者說大部分企業(yè)當前使用的也是Java8。那么既然Java8的應用如此之廣泛,一定有一些亮點所在:
- Lambda 表達式
- 函數式接口
- 方法引用與構造器引用
- Stream API
- 接口中的默認方法與靜態(tài)方法
- 新時間日期API
- 其他新特性
速度更快、代碼更少(增加了新的語法 Lambda 表達式)、強大的 Stream API、便于并行、最大化減少空指針異常 Optional。
2.為什么要使用Lambda表達式?
Lambda 是一個 匿名函數 數,我們可以把 Lambda表達式理解為是 一段可以傳遞的 代碼(將代碼像數據一樣進行傳遞)??梢詫懗龈啙崱⒏`活的代碼。作為一種更緊湊的代碼風格,使Java語言表達能力得到了提升。
3.Lambda表達式的基本語法
Lambda 表達式在Java 語言中引入了一個新的語法元素和操作符。這個操作符為 “ -> ” , 該操作符被稱為 Lambda 操作符或剪頭操作符。
它將 Lambda 分為兩個部分:
- 左側 :指定了 Lambda 表達式需要的所有參數。
- 右側 :指定了 Lambda 體,即 Lambda 表達式要執(zhí)行的功能。
具體的就看下面的代碼案例。
package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* Lambda 表達式的基礎語法:
* Java8中引入了一個新的操作符 "->"
* 該操作符稱為 箭頭操作符 或 Lambda操作符
* 箭頭操作符將 Lambda 表達式拆分成兩部分:
*
* 左側:Lambda 表達式的參數列表
* 右側:Lambda 表達式中所需執(zhí)行的功能, 即 Lambda 體
*
* Lambda 表達式需要“函數式接口”的支持
* 函數式接口:接口中只有一個抽象方法的接口, 稱為函數式接口
* 可以使用注解 @FunctionalInterface 修飾, 可以檢查是否是函數式接口
*/
public class MyTest2 {
/**
* 語法格式一:無參數,無返回值
* () -> System.out.println("Hello World!!!");
*/
@Test
public void test1() {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello World!!!");
}
};
r1.run();
System.out.println("---------------------------");
Runnable r2 = () -> System.out.println("Hello World!!!");
r2.run();
}
}

package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* Lambda 表達式的基礎語法:
* Java8中引入了一個新的操作符 "->"
* 該操作符稱為 箭頭操作符 或 Lambda操作符
* 箭頭操作符將 Lambda 表達式拆分成兩部分:
*
* 左側:Lambda 表達式的參數列表
* 右側:Lambda 表達式中所需執(zhí)行的功能, 即 Lambda 體
*
* Lambda 表達式需要“函數式接口”的支持
* 函數式接口:接口中只有一個抽象方法的接口, 稱為函數式接口
* 可以使用注解 @FunctionalInterface 修飾, 可以檢查是否是函數式接口
*/
public class MyTest2 {
/**
* 語法格式二:有一個參數,無返回值
* (x) -> System.out.println(x)
* 此語法格式中小括號可以省略不寫,等價于
* x -> System.out.println(x)
*/
@Test
public void test2() {
Consumer<String> consumer = (str) -> System.out.println(str);
consumer.accept("Lambda表達式真好用....");
}
}

package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* Lambda 表達式的基礎語法:
* Java8中引入了一個新的操作符 "->"
* 該操作符稱為 箭頭操作符 或 Lambda操作符
* 箭頭操作符將 Lambda 表達式拆分成兩部分:
*
* 左側:Lambda 表達式的參數列表
* 右側:Lambda 表達式中所需執(zhí)行的功能, 即 Lambda 體
*
* Lambda 表達式需要“函數式接口”的支持
* 函數式接口:接口中只有一個抽象方法的接口, 稱為函數式接口
* 可以使用注解 @FunctionalInterface 修飾, 可以檢查是否是函數式接口
*/
public class MyTest2 {
/**
* 語法格式三:有兩個以上的參數,有返回值,并且 Lambda 體中有多條語句
*/
@Test
public void test3() {
Comparator<Integer> comparator = (x,y) -> {
System.out.println("函數式接口....");
return Integer.compare(x,y);
};
}
}
package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* Lambda 表達式的基礎語法:
* Java8中引入了一個新的操作符 "->"
* 該操作符稱為 箭頭操作符 或 Lambda操作符
* 箭頭操作符將 Lambda 表達式拆分成兩部分:
*
* 左側:Lambda 表達式的參數列表
* 右側:Lambda 表達式中所需執(zhí)行的功能, 即 Lambda 體
*
* Lambda 表達式需要“函數式接口”的支持
* 函數式接口:接口中只有一個抽象方法的接口, 稱為函數式接口
* 可以使用注解 @FunctionalInterface 修飾, 可以檢查是否是函數式接口
*/
public class MyTest2 {
/**
* 語法格式四:若 Lambda 體中只有一條語句,
* 則 return 和 大括號都可以省略不寫
* Lambda 表達式的參數列表的數據類型可以省略不寫,
* 因為JVM編譯器通過上下文推斷出,數據類型,即 “類型推斷”
*/
@Test
public void test4() {
Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);
}
}
上述 Lambda 表達式中的參數類型都是由編譯器推斷得出的。Lambda 表達式中無需指定類型,程序依然可以編譯,這是因為 javac 根據程序的上下文,在后臺
推斷出了參數的類型。Lambda 表達式的類型依賴于上下文環(huán)境,是由編譯器推斷出來的。這就是所謂的 “類型推斷”。
4.自定義函數式接口
只包含一個抽象方法的接口,稱為 函 數 式 接 口。
你可以通過 Lambda 表達式來創(chuàng)建該接口的對象。(若 Lambda表達式拋出一個受檢異常,那么該異常需要在目標接口的抽象方法上進行聲明)
我們可以在任意函數式接口上使用 @FunctionalInterface 注解,這樣做可以檢查它是否是一個函數式接口,同時 javadoc 也會包含一條聲明,說明這個接口是一個函數式接口。
就像Runnable接口一樣,它就是一個典型的函數式接口。
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface {@code Runnable} is used
* to create a thread, starting the thread causes the object's
* {@code run} method to be called in that separately executing
* thread.
* <p>
* The general contract of the method {@code run} is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
那么我們肯定也可以自定義函數式接口了,首先是沒有泛型的自定義函數式接口。
package com.szh.java8.two;
/**
*
*/
@FunctionalInterface
public interface MyFunction {
public String getValue(String str);
}
package com.szh.java8.two;
/**
*
*/
public class TestLambda {
private static String strHandler(String str,MyFunction mf) {
return mf.getValue(str);
}
public static void main(String[] args) {
//去除首尾空格
String trimStr = strHandler("\t\t\t 張起靈-小哥 ",(str) -> str.trim());
System.out.println(trimStr);
//轉為大寫
String upperStr = strHandler("hello world",str -> str.toUpperCase());
System.out.println(upperStr);
//部分截取
String newStr = strHandler("學Java的冷少",(str) -> str.substring(0,5));
System.out.println(newStr);
}
}

下面再來看一個帶泛型的函數式接口。
package com.szh.java8.three;
/**
*
*/
@FunctionalInterface
public interface MyFunction2<T,R> {
public R getValue(T t1,T t2);
}
package com.szh.java8.three;
import com.szh.java8.two.MyFunction;
/**
*
*/
public class TestLambda {
private static void operation(Long l1,Long l2,MyFunction2<Long,Long> mf) {
System.out.println(mf.getValue(l1,l2));
}
public static void main(String[] args) {
//和
operation(100L,200L,(x,y) -> x + y);
//積
operation(300L,500L,(x,y) -> x * y);
}
}

作為參數傳遞 Lambda 表達式:為了將 Lambda 表達式作為參數傳遞 ,接收 Lambda 表達式的參數類型必須是與該 Lambda 表達式兼容的函數式接口的類型。
以上就是深入理解Java8新特性之Lambda表達式的基本語法和自定義函數式接口的詳細內容,更多關于Java Lambda表達式的資料請關注腳本之家其它相關文章!
相關文章
Spring Boot 2.0.0 終于正式發(fā)布-重大修訂版本
北京時間 2018 年 3 月 1 日早上,如約發(fā)布的 Spring Boot 2.0 在同步至 Maven 倉庫時出現(xiàn)問題,導致在 GitHub 上發(fā)布的 v2.0.0.RELEASE 被撤回2018-03-03
淺談String類型等值比較引起的“==”、“equals()”和“hashCode”思考
這篇文章主要介紹了淺談String類型等值比較引起的“==”、“equals()”和“hashCode”思考。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
springboot的application.yml配置port不生效的解決方案
這篇文章主要介紹了springboot的application.yml配置port不生效的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
淺析Java中對象的創(chuàng)建與對象的數據類型轉換
這篇文章主要介紹了Java中對象的創(chuàng)建與對象的數據類型轉換,是Java入門學習中的基礎知識,需要的朋友可以參考下2016-01-01

