本文翻译自: Java 8 Method Reference
在 Java 8 中提供了一个叫做方法引用的新特性。方法引用用于在函数式接口上引用其他方法。它是 Lambda 表达式的一种更简单的形式。当你使用 Lambda 表达式仅仅是为了引用另一个方法时,你可以使用方法引用来替换这些语句。在本教程中,我们将详细的解释方法引用的概念。
在 Java 中,方法引用有以下几种类型:
你可以引用一个类中的静态方法。下面是静态方法引用的语法和示例。
语法
ClassName::staticMethodName
示例1
在接下来的示例中,我们将定义一个函数式接口并引用一个静态方法来实现接口中的 eat()
方法。
interface Eatable { void eat(); } public class MethodReference { public static void eatSomething() { System.out.println("我在吃饭..."); } public static void main(String[] args) { // 引用静态方法 Eatable eatable = MethodReference::eatSomething; // 它等同于以下的 Lambda 表达式 Eatable eatable1 = () -> MethodReference.eatSomething(); eatable.eat(); eatable1.eat(); } }
运行结果:
我在吃饭... 我在吃饭...
示例2
在这个示例中,我们使用 Java 中内置的函数式接口 Runnable 来引用一个静态方法。
public class MethodReference2 { public static void threadStatus() { System.out.println("线程正在运行中..."); } public static void main(String[] args) { // 使用 Runnable 中的 run 方法引用静态方法 threadStatus() Thread t2 = new Thread(MethodReference2::threadStatus); t2.start(); } }
运行结果:
线程正在运行中..
示例3
你也可以使用对应的参数列表来引用方法重载中的指定方法。在接下来的示例中,我们定义了三个重载方法来用于方法引用。
import java.util.function.BiFunction; class Arithmetic { // int, int public static int add(int a, int b) { return a + b; } // int, float public static float add(int a, float b) { return a + b; } // float, float public static float add(float a, float b) { return a + b; } } public class MethodReference3 { public static void main(String[] args) { // 两个 Integer 类型的参数和一个 Integer 类型的返回值 BiFunction<Integer, Integer, Integer> adder1 = Arithmetic::add; // (Integer, Float) 类型的参数列表和一个 Float 类型的返回值 BiFunction<Integer, Float, Float> adder2 = Arithmetic::add; // (Float, Float) 类型的参数列表和一个 Float 类型的返回值 BiFunction<Float, Float, Float> adder3 = Arithmetic::add; int result1 = adder1.apply(10, 20); float result2 = adder2.apply(10, 20.0f); float result3 = adder3.apply(10.0f, 20.0f); System.out.println(result1); System.out.println(result2); System.out.println(result3); } }
运行结果:
30 30.0 30.0
像静态方法一样,你也可以引用实例方法。在下面的示例中,我们将展示如何对实例方法进行方法引用。
语法
objectInstance::instanceMethodName
示例
在这个示例中,我们将引用一个对象的非静态的方法。你可以通过类对象或匿名对象来引用方法。
interface Eatable { void eat(); } public class MethodReference4 { public void eatSomething() { System.out.println("xx正在吃饭..."); } public static void main(String[] args) { // 创建一个对象实例 MethodReference4 methodReference = new MethodReference4(); // 通过实例名引用非静态方法 Eatable eatable = methodReference::eatSomething; eatable.eat(); // 引用匿名对象的非静态方法 Eatable eatable2 = new MethodReference4()::eatSomething; eatable2.eat(); } }
运行结果:
xx正在吃饭... xx正在吃饭...
你可以使用 new
关键字来引用一个构造方法。在这里,我们使用函数式接口来引用一个构造函数。
语法
ClassName::new
示例
interface Messageable { Message getMessage(String msg); } class Message { Message(String msg) { System.out.println(msg); } } public class MethodReference5 { public static void main(String[] args) { // 引用一个构造函数 Messageable hello = Message::new; hello.getMessage("Hello"); } }
通过这些示例我们可以发现,方法引用就是将 Lambda 表达式的参数直接转发到了引用的方法上,并将该方法的返回值作为 Lambda 表达式的返回值进行返回 (构造方法返回了对象本身)。