1.寫在前面
目前我們學習Java主要用到的應該就是Java8了,或者說大部分企業當前使用的也是Java8,那么既然Java8的應用如此之廣泛,一定有一些亮點所在:
- Lambda 運算式
- 函式式介面
- 方法參考與構造器參考
- Stream API
- 介面中的默認方法與靜態方法
- 新時間日期API
- 其他新特性
速度更快、代碼更少(增加了新的語法 Lambda 運算式)、強大的 Stream API、便于并行、最大化減少空指標例外 Optional,
2.為什么要使用Lambda運算式?
Lambda 是一個 匿名函式 數,我們可以把 Lambda運算式理解為是 一段可以傳遞的 代碼(將代碼像資料一樣進行傳遞),可以寫出更簡潔、更靈活的代碼,作為一種更緊湊的代碼風格,使Java語言表達能力得到了提升,
3.Lambda運算式的基本語法
Lambda 運算式在Java 語言中引入了一個新的語法元素和運算子,這個運算子為 “ -> ” , 該運算子被稱為 Lambda 運算子或剪頭運算子,
它將 Lambda 分為兩個部分:
- 左側 :指定了 Lambda 運算式需要的所有引數,
- 右側 :指定了 Lambda 體,即 Lambda 運算式要執行的功能,
具體的就看下面的代碼案例,
package com.szh.java8;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
/**
* Lambda 運算式的基礎語法:
* Java8中引入了一個新的運算子 "->"
* 該運算子稱為 箭頭運算子 或 Lambda運算子
* 箭頭運算子將 Lambda 運算式拆分成兩部分:
*
* 左側:Lambda 運算式的引數串列
* 右側:Lambda 運算式中所需執行的功能, 即 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 運算式中所需執行的功能, 即 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 運算式中所需執行的功能, 即 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 運算式中所需執行的功能, 即 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 運算式的型別依賴于背景關系環境,是由編譯器推斷出來的,這就是所謂的 “型別推斷”,
4.自定義函式式介面
只包含一個抽象方法的介面,稱為 函 數 式 接 口,
你可以通過 Lambda 運算式來創建該介面的物件,(若 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 運算式兼容的函式式介面的型別,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/353384.html
標籤:java
