方法引用
1、语法引用符
双冒号::
为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可通过双冒号来引用该方法作为Lambda的替代者。
语义分析
如:System.out
对象中有一个重载的println
方法,其中System.out
是已经存在的对象,其中println
方法是已经存在的方法,所以有2种写法:
- Lambda表达式写法:
s -> System.out.println(s)
- 方法引用写法:
System.out::println
第一种语义指:拿到参数之后经Lambda之手,继而传给System.out.println方法去处理。
第二种语义指:直接让System.out
中的println
方法来取代Lambda。
注:Lambda中传递的参数一定是方法引用中的那个方法可以接收的类型,否则会报异常。
2、通过对象名引用成员方法
对象一定要是存在的,不然无法使用。
PrintString.java
@FunctionalInterface
public interface PrintString {
String print(String str);
}
StringToUppercase.java
public class StringToUppercase {
public String stringToUppercase(String str){
return str.toUpperCase();
}
}
StringToUppercaseTest.java
public class StringToUppercaseTest {
public static void printUppercase(PrintString p){
System.out.println(p.print("heroC"));
}
public static void main(String[] args) {
StringToUppercase obj = new StringToUppercase();
// 使用方法引用,实现PrintString接口的print方法,注重方法体,该方法需要返回Stirng类型的数据。
// 方法体实则是,通过obj对象调用了stringToUppercase方法。而这个方法作为了函数式接口print抽象方法的具体实现。将参数传递进去执行结果。参数可前后推导
printUppercase(obj::stringToUppercase);
/*
printUppercase()方法是使用的函数式接口因此需要实现PrintString中的print方法,又因为给print方法传递了字符串“heroC”
printUppercase(new PrintString(){
@Override
String print(String str){
obj.stringToUppercase(String str);
}
});
*/
}
}
// 输出:HEROC
3、通过类名称引用静态方法
PrintString.java
@FunctionalInterface
public interface PrintString {
String print(String str);
}
StringToUppercase.java
public class StringToUppercase {
public static String stringToLowercase(String str){
return str.toLowerCase();
}
}
StringToUppercaseTest.java
public class StringToUppercaseTest {
public static void printUppercase(PrintString p){
System.out.println(p.print("heroC"));
}
public static void main(String[] args) {
// 使用方法引用,实现PrintString接口的print方法,注重方法体,该方法需要返回Stirng类型的数据。
// 方法体实则是,通过方法名调用了stringToLowercase静态方法。
// 将参数传递进去执行结果。参数可前后推导
printUppercase(StringToUppercase::stringToLowercase);
}
}
// 输出:heroc
4、通过super引用成员方法
使用前提,必须有子父类关系。
PrintInfo.java
@FunctionalInterface
public interface PrintInfo {
void print();
}
Human.java
public class Human {
public void printHuman(){
System.out.println("我是父类Human");
}
}
Man.java
public class Man extends Human {
@Override
public void printHuman() {
System.out.println("我是子类Man");
}
public void method(PrintInfo prin){
prin.print();
}
public void printMethod(){
// 通过方法引用,调用super父类的printHuman方法
method(super::printHuman);
}
public static void main(String[] args) {
new Man().printMethod();
}
}
// 输出:我是父类Human
5、通过this引用成员方法
PrintInfo.java
@FunctionalInterface
public interface PrintInfo {
void print();
}
Human.java
public class Human {
public void printHuman(){
System.out.println("通过this引用打印");
}
public void method(PrintInfo prin){
prin.print();
}
public void methodTest(){
// 调用this中的printHuman方法重写接口的print方法
method(this::printHuman);
}
public static void main(String[] args) {
new Human().methodTest();
}
}
// 输出:通过this引用打印
6、类的构造器引用
使用类名::new
的格式表示
PersonInterface.java
@FunctionalInterface
public interface PersonInterface {
Person func(String name);
}
Person.java
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
Test.java
public class Test {
public static void method(PersonInterface per){
Person person = per.func("heroC");
System.out.println(person);
}
public static void main(String[] args) {
// 将PersonInterface的func方法重写了,调用了Person构造器,因为传递了heroC字符串
// 会自动调用带参构造器
method(Person::new);
}
}
// 输出:Person{name='heroC'}
7、数组的构造器引用
如:int[]::new
ArrayInterface.java
public interface ArrayInterface {
int[] createArray(int len);
}
ArrayImp.java
public class ArrayImp {
public static int[] method(int len, ArrayInterface arr){
return arr.createArray(len);
}
public static void main(String[] args) {
// 数组构造器引用
System.out.println( method(10, int[]::new).length );
}
}
// 输出:10