Java 8 中的特性 - 方法引用
Java 8 Feature - Method References
本文翻译自: Java 8 Method Reference
Method References
在 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 表达式的返回值进行返回 (构造方法返回了对象本身)。