方法引用可以有不同的形式,取決於方法的來源和使用場景。主要有四種形式:
-
靜態方法引用:
ClassName::staticMethod
示例:
Math::max; // 等價於 (a, b) -> Math.max(a, b)
-
例項方法引用(特定物件的方法):
instance::instanceMethod
示例:
System.out::println; // 等價於 x -> System.out.println(x)
-
例項方法引用(任意物件的方法):
ClassName::instanceMethod
示例:
String::toLowerCase; // 等價於 x -> x.toLowerCase()
-
構造方法引用:
ClassName::new
示例:
ArrayList::new; // 等價於 () -> new ArrayList<>()
- 方法引用有四種主要形式:靜態方法引用、例項方法引用(特定物件或任意物件)、以及構造方法引用。它們是簡化 Lambda 表示式的方式。
import java.util.function.Supplier;
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static void main(String[] args) {
// 建構函式引用
Supplier<Person> personSupplier = Person::new;
// 例項方法引用(任意物件)
Supplier<String> nameSupplier = personSupplier.get()::getName;
// 使用例項方法引用
System.out.println(nameSupplier.get()); // 列印 name
}
}
Supplier
是 Java 8 引入的一個函式式介面,位於 java.util.function
包中。它的主要作用是提供一個結果,不接收任何輸入引數。Supplier
常用於需要延遲計算或惰性求值的場景,也就是在需要時提供一個值,而不立即計算或建立它。
Supplier
的定義
Supplier
是一個泛型介面,定義如下:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
T
:代表返回值的型別。get()
:是唯一需要實現的方法,呼叫它會返回型別T
的值。
使用場景
Supplier
通常用於生成或提供一個值、物件,或者用於懶載入。當我們想要推遲某些計算直到呼叫方真正需要它時,Supplier
就非常有用。
示例 1:基本使用 Supplier
下面的例子展示瞭如何使用 Supplier
來提供一個字串:
import java.util.function.Supplier;
public class SupplierExample {
public static void main(String[] args) {
// 使用 Supplier 提供一個字串
Supplier<String> stringSupplier = () -> "Hello, World!";
// 呼叫 get() 獲取結果
System.out.println(stringSupplier.get()); // 輸出 "Hello, World!"
}
}
在這個例子中,Supplier<String>
是一個返回字串的 Supplier
,呼叫 get()
方法時返回 "Hello, World!"
。
示例 2:使用 Supplier
延遲計算
Supplier
還可以用於延遲計算,例如只有在需要的時候才計算某個值:
import java.util.function.Supplier;
public class LazyEvaluationExample {
public static void main(String[] args) {
Supplier<Double> randomSupplier = () -> Math.random();
// 延遲生成隨機數
System.out.println("First call: " + randomSupplier.get());
System.out.println("Second call: " + randomSupplier.get());
}
}
每次呼叫 randomSupplier.get()
都會生成一個新的隨機數。這就是 Supplier
的延遲計算的優勢,只有在真正需要時才會執行。
示例 3:使用 Supplier
建立物件
Supplier
還可以用於建立物件,尤其是在建構函式引用中非常常見。
import java.util.function.Supplier;
public class Person {
private String name;
public Person() {
this.name = "John Doe";
}
public String getName() {
return name;
}
public static void main(String[] args) {
// 使用 Supplier 提供一個 Person 例項
Supplier<Person> personSupplier = Person::new;
// 延遲建立 Person 物件
Person person = personSupplier.get();
System.out.println("Person's name: " + person.getName()); // 輸出 "John Doe"
}
}
在這個例子中,Person::new
是構造方法引用,返回一個新的 Person
例項。Supplier
提供了一種惰性載入物件的方式,只有在 get()
被呼叫時才建立 Person
物件。
Supplier<T>
是一個不接受任何引數,但會返回型別T
的值的函式式介面。- 它用於延遲計算、惰性求值或者物件建立。
- 透過呼叫
get()
方法,可以獲取由Supplier
提供的值或物件。
Supplier
常用於需要提供值的場景,特別是在不確定何時需要這個值時,它是延遲計算的有效工具。
如果你需要一個能夠接受引數並返回結果的函式式介面,那麼應該使用 Java 8 中的另一個函式式介面,而不是 Supplier
。Supplier
只適用於不需要引數的場景。如果需要傳遞引數並返回結果,可以使用以下介面:
1. Function<T, R>
:接收一個引數並返回一個結果
- 定義:
Function<T, R>
接收一個型別為T
的引數,並返回一個型別為R
的結果。
示例:使用 Function
接收引數並返回結果
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
// 定義一個 Function:接收一個字串並返回它的長度
Function<String, Integer> lengthFunction = str -> str.length();
// 呼叫 apply() 方法傳遞引數並獲取結果
System.out.println(lengthFunction.apply("Hello")); // 輸出 5
}
}
T
:輸入引數的型別。R
:返回值的型別。apply(T t)
:方法用於接收輸入引數並返回結果。
2. BiFunction<T, U, R>
:接收兩個引數並返回一個結果
- 定義:
BiFunction<T, U, R>
接收兩個引數,T
和U
,並返回一個型別為R
的結果。
示例:使用 BiFunction
接收兩個引數並返回結果
import java.util.function.BiFunction;
public class BiFunctionExample {
public static void main(String[] args) {
// 定義一個 BiFunction:接收兩個整數並返回它們的乘積
BiFunction<Integer, Integer, Integer> multiplyFunction = (a, b) -> a * b;
// 呼叫 apply() 方法傳遞兩個引數並獲取結果
System.out.println(multiplyFunction.apply(5, 3)); // 輸出 15
}
}
T
:第一個輸入引數的型別。U
:第二個輸入引數的型別。R
:返回值的型別。apply(T t, U u)
:方法用於接收兩個輸入引數並返回結果。
3. Consumer<T>
:接收一個引數但不返回結果
- 定義:
Consumer<T>
接收一個型別為T
的引數,但不返回任何結果(類似於void
方法)。
示例:使用 Consumer
接收引數但不返回結果
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
// 定義一個 Consumer:接收一個字串並列印出來
Consumer<String> printConsumer = str -> System.out.println(str);
// 呼叫 accept() 方法傳遞引數
printConsumer.accept("Hello, World!"); // 輸出 "Hello, World!"
}
}
T
:輸入引數的型別。accept(T t)
:方法用於接收輸入引數,不返回結果。
4. BiConsumer<T, U>
:接收兩個引數但不返回結果
- 定義:
BiConsumer<T, U>
接收兩個型別的引數,但不返回結果。
示例:使用 BiConsumer
接收兩個引數但不返回結果
import java.util.function.BiConsumer;
public class BiConsumerExample {
public static void main(String[] args) {
// 定義一個 BiConsumer:接收兩個引數並列印
BiConsumer<String, Integer> printConsumer = (name, age) ->
System.out.println(name + " is " + age + " years old");
// 呼叫 accept() 方法傳遞兩個引數
printConsumer.accept("Alice", 25); // 輸出 "Alice is 25 years old"
}
}
總結:
Supplier<T>
:不接收任何引數,返回型別T
的結果。Function<T, R>
:接收一個引數,返回型別R
的結果。BiFunction<T, U, R>
:接收兩個引數,返回型別R
的結果。Consumer<T>
:接收一個引數,不返回結果。BiConsumer<T, U>
:接收兩個引數,不返回結果。
根據需要選擇合適的函式式介面來處理帶參的場景。