方法引用替代的概念
方法引用是 Java 8 引入的一种简化 Lambda 表达式的语法形式。
当 Lambda 表达式的 主体部分仅仅是调用一个已有方法 时,可以用方法引用来替代 Lambda 表达式,使代码更简洁。
方法引用的语法:
ClassName::methodName
它是 Lambda 表达式的简化形式,并且依赖于 函数式接口。
方法引用的类型
方法引用主要有以下四种类型:
1. 静态方法引用
- 格式:
ClassName::staticMethod
- Lambda 表达式中如果调用的是某个类的静态方法,可以使用静态方法引用。
示例:
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
public class MethodReferenceExample {
public static void main(String[] args) {
// 使用 Lambda 表达式
Converter<String, Integer> lambdaConverter = s -> Integer.parseInt(s);
// 使用静态方法引用
Converter<String, Integer> methodRefConverter = Integer::parseInt;
System.out.println(methodRefConverter.convert("123")); // 输出 123
}
}
2. 实例方法引用(特定对象的方法)
- 格式:
instance::instanceMethod
- 如果 Lambda 表达式中调用的是一个特定对象的实例方法,可以使用实例方法引用。
示例:
@FunctionalInterface
interface Printer {
void print(String message);
}
public class MethodReferenceExample {
public static void main(String[] args) {
Printer lambdaPrinter = message -> System.out.println(message);
// 使用实例方法引用
Printer methodRefPrinter = System.out::println;
methodRefPrinter.print("Hello, Method Reference!"); // 输出 Hello, Method Reference!
}
}
3. 实例方法引用(任意对象的方法)
- 格式:
ClassName::instanceMethod
- 如果 Lambda 表达式中调用的是任意对象的实例方法(即接口方法的第一个参数作为调用者),可以使用这种形式。
示例:
import java.util.Arrays;
import java.util.List;
public class MethodReferenceExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 使用 Lambda 表达式
names.forEach(name -> System.out.println(name));
// 使用方法引用
names.forEach(System.out::println); // 等价于 name -> System.out.println(name)
}
}
另一个示例:
@FunctionalInterface
interface StringProcessor {
String process(String input);
}
public class MethodReferenceExample {
public static void main(String[] args) {
StringProcessor lambdaProcessor = s -> s.toUpperCase();
// 使用方法引用
StringProcessor methodRefProcessor = String::toUpperCase;
System.out.println(methodRefProcessor.process("hello")); // 输出 HELLO
}
}
4. 构造方法引用
- 格式:
ClassName::new
- 如果 Lambda 表达式的功能是创建一个对象实例,可以用构造方法引用。
示例:
@FunctionalInterface
interface Factory<T> {
T create();
}
public class MethodReferenceExample {
public static void main(String[] args) {
// 使用 Lambda 表达式
Factory<String> lambdaFactory = () -> new String();
// 使用构造方法引用
Factory<String> methodRefFactory = String::new;
String str = methodRefFactory.create(); // 等价于 new String()
System.out.println(str); // 输出空字符串
}
}
带参数的构造方法引用:
@FunctionalInterface
interface Factory<T, U> {
T create(U arg);
}
public class MethodReferenceExample {
public static void main(String[] args) {
// 使用 Lambda 表达式
Factory<StringBuilder, String> lambdaFactory = str -> new StringBuilder(str);
// 使用构造方法引用
Factory<StringBuilder, String> methodRefFactory = StringBuilder::new;
StringBuilder sb = methodRefFactory.create("Hello, World!");
System.out.println(sb); // 输出 Hello, World!
}
}
Lambda 表达式与方法引用的对比
-
Lambda 表达式:
Lambda 是直接对行为逻辑的表达,比如:Runnable r = () -> System.out.println("Running!");
-
方法引用:
如果 Lambda 表达式直接调用了一个已有方法,可以用方法引用替代:Runnable r = System.out::println;
两者功能相同,但方法引用更加简洁直观。
方法引用的优点
- 简洁性:方法引用去掉了 Lambda 表达式中不必要的部分,使代码更易读。
- 直观性:通过方法引用,直接表达调用现有方法的意图,而不用重新描述逻辑。
- 提高代码复用性:复用已有方法逻辑,而不是在 Lambda 表达式中重新实现。
方法引用的限制
-
必须与函数式接口结合使用
方法引用的目标必须与函数式接口的抽象方法签名匹配。 -
功能限制
方法引用只能用于已有方法的调用,无法用来定义新的逻辑。如果逻辑比较复杂,仍需使用 Lambda 表达式。
总结
- 方法引用 是 Lambda 表达式的简化形式,适用于直接调用已有方法的场景。
- 常见类型包括静态方法引用、实例方法引用和构造方法引用。
- 它使代码更加简洁和可读,但对于复杂的行为逻辑,仍需要使用 Lambda 表达式。