注意:方法引用返回的是一个函数式接口对象(该函数式接口抽象方法被引用方法替代了,调用抽象方法实际上就是调用引用的方法)。?
比如:Function<String, String> function = String::toUpperCase;
Java 中的双冒号(::)用于方法引用,它可以简化 Lambda 表达式的书写。总结一下双冒号的使用情况,并举例说明:
静态方法引用:
类名::静态方法名
- 用于引用类的静态方法。
示例:
// 定义一个函数式接口 interface MathOperation { int operation(int a, int b); } // 定义一个静态方法 static int add(int a, int b) { return a + b; } public static void main(String[] args) { // 使用静态方法引用 MathOperation operation = Math::add; int result = operation.operation(10, 5); // 调用静态方法 System.out.println(result); // 输出:15 }
实例方法引用:
对象::实例方法名
- 用于引用对象的实例方法。
示例:
// 定义一个函数式接口 interface StringLength { int getLength(String str); } public static void main(String[] args) { StringLength length = String::length; // 使用实例方法引用 int len = length.getLength("Hello"); // 调用实例方法 System.out.println(len); // 输出:5 }
类名引用普通方法:
类名::方法名
- 用于引用类的普通方法(非静态方法)。
- 可以认为是底层new了一个该类名的对象,然后引用该实例方法。
示例:
// 定义一个函数式接口 interface StringFormatter { String format(String str); } // 定义一个普通方法 String toUpperCase(String str) { return str.toUpperCase(); } public static void main(String[] args) { StringFormatter formatter = String::toUpperCase; // 使用类名引用普通方法 String result = formatter.format("hello"); // 调用普通方法 System.out.println(result); // 输出:HELLO }
构造函数引用:
类名::new
- 用于引用类的构造函数。
- 类名::new出来的是一个函数式接口对象。因为Person的构造方法参数与PersonFactory接口的create方法参数类型和返回值是一样的,所以create的实例方法已经变成了Person类的构造方法,所以该函数式接口已经被实现了。
示例:
// 定义一个函数式接口 interface PersonFactory { Person create(String name, int age); } class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } } public static void main(String[] args) { PersonFactory factory = Person::new; // 使用构造函数引用 Person person = factory.create("Alice", 25); // 调用构造函数 System.out.println(person.getName()); // 输出:Alice System.out.println(person.getAge()); // 输出:25 }
双冒号(::)可以提高代码的可读性和简洁性,特别适用于函数式编程和集合操作等场景。
方法引用?::可以认为是代替了一部分的lambda表达式,都是为函数式接口服务。
解析:
函数式接口:?
@FunctionalInterface public interface AFactory<T> { T getObject(String a); }
String类(我自己瞎写的):
public class String{
T toT(String s){
....
}
}
lambda表达式:
(s)-> {
? ? ? ? return a.toT(s);
}
方法引用:
String::toT
总结:
1.可以看出方法引用跟函数式接口的返回值和方法参数一样。
2.跟lambda表达式相比,不用标明方法参数,因为会调用跟函数式接口方法参数和返回值一样的方法。也不用实现,因为引用的方法就是实现。