方法引用基本介绍:
为了省去Lambda的语法格式,只要“引用”过去就行了
双冒号::为引用运算符,而他所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
public class Demo01Printable { //定义一个方法,参数传递Printable接口,对字符串进行打印 public static void printString(Printable p){ p.print("hello world"); } public static void main(String[] args) { //调用printString方法,方法的参数Printable是一个函数式接口,所以可以传递Lambda printString((s)->{ System.out.println(s); }); /* * 分析: * Lambda表达式的目的,打印参数传递的字符串 * 把参数s,传递给了System.out对象,调用out对象中的方法println对字符串进行了输出 * 注意: * 1.System.out对象是已经存在的 * 2.println方法也是已经存在的 * 所以我们可以使用方法引用优化Lambda表达式 * 可以使用System.out方法直接调用println方法 * */ printString(System.out::println); } }
通过对象名引用成员方法:
public class MethodRerObject { //定义一个成员方法,传递字符串,把字符串按照大写输出 public void printUpperCaseString(String str){ System.out.println(str.toUpperCase()); } } @FunctionalInterface public interface Printable { void print(String s); } /* * 通过对象名引用成员方法 * 使用前提是对象名是已经存在的,成员方法也是存在的 * 就可以使用对象名来引用成员方法 * */ public class Demo01ObjectMethodReference { //定义一个方法,方法的参数传递Printable接口 public static void printString(Printable p){ p.print("hello"); } public static void main(String[] args) { //调用printString方法,方法的参数Printable是一个函数式接口,所以可以传递Lambda表达式 printString((s)->{ //创建MethodRerObject对象 MethodRerObject obj=new MethodRerObject(); //调用MethodRerObject对象中的成员方法printUpperCaseString,把字符串按照大写输出 obj.printUpperCaseString(s); }); /* * 使用方法引用来优化Lambda * 对象是已经存在的MethodRerObject * 成员方法也是已经存在的printUpperCaseString * 所以我们可以使用对象名来引用成员方法 * */ MethodRerObject obj=new MethodRerObject(); printString(obj::printUpperCaseString); } }
通过类名引用静态成员:
@FunctionalInterface public interface Calcable { //定义一个抽象方法,传递一个整数,对整数进行绝对值计算并返回 int calsAbs(int num); } /* * 通过类名引用静态成员方法 * 类已经存在,静态成员方法也已经存在 * 就可以通过类名直接引用静态成员方法 * */ public class Demo01StaticMethodReference { //定义一个方法,方法的参数传递要计算绝对值的整数,和函数式接口Calcable public static int method(int number,Calcable c){ return c.calsAbs(number); } public static void main(String[] args) { //调用method方法,传递计算绝对值的整数和Lambda表达式 int number=method(-10,(n)->{ //对参数进行绝对值的计算并返回结果 return Math.abs(n); }); System.out.println(number); /* * 使用方法引用优化Lambda表达式 * Math类是存在的 * abs计算绝对值的静态方法也是已经存在的 * 所以我们可以直接通过类名引用静态方法 * */ int num2 = method(-10, Math::abs); System.out.println(num2); } }
通过super引用成员方法:
如果存在继承关系,当Lambda中需要出现super调用时,也可以使用方法引用进行代替。
/* * 定义见面的函数式接口 * */ @FunctionalInterface public interface Greatable { //定义一个见面的方法 void greet(); } /* * 定义父类 * */ public class Human { //定义一个sayHello的方法 public void sayHello(){ System.out.println("Hello 我是Human"); } } /* * 定义子类 * */ public class man extends Human{ //子类重写父类sayHello的方法 @Override public void sayHello(){ System.out.println("Hello 我是man!"); } //定义一个方法参数传递Greatable接口 public void method(Greatable g){ g.greet(); } public void show(){ //调用method方法,方法的参数Greatable是一个函数式接口,所以可以传递Lambda表达式 /* method(()->{ //创建Human对象 Human h=new Human(); //调用父类的sayHello方法 h.sayHello(); });*/ //因为有子父类关系,所以存在一个关键字super,代表父类,所以我们可以直接使用super调用父类的成员方法 /*method(()->{ super.sayHello(); });*/ /* * 使用super引用父类的成员方法 * super是已经存在的 * 父类的成员方法sayHello也是已经存在的 * 所以我们可以直接使用super引用父类的成员方法 * */ method(super::sayHello); } public static void main(String[] args) { new man().show(); } }
通过this引用成员方法:
/* * 定义一个富有的函数式接口 * */ @FunctionalInterface public interface Rich { //定义一个想买什么就买什么的方法 void buy(); } /* * 通过this引用本类的成员方法 * */ public class Husband { //定义一个买房子的方法 public void buyHouse(){ System.out.println("北京二环买一套四合院"); } //定义一个结婚的方法,参数传递Rich接口 public void marry(Rich r){ r.buy(); } //定义一个非常高兴的方法 public void soHappy(){ //调用结婚的方法,方法的参数Rich是一个函数式接口,可以传递Lambda表达式 /*marry(()->{ //使用this.成员方法,调用本类买房子的方法 this.buyHouse(); });*/ /* * 使用方法引用优化Lambda表达式 * this是已经存在的 * 本类的成员方法buyHouse也是已经存在的 * 所以我们可以直接使用this引用本类的成员方法buyHouse * */ marry(this::buyHouse); } public static void main(String[] args) { new Husband().soHappy(); } }
构造方法引用:
/* * 定义一个创建Person对象的函数式接口 * */ @FunctionalInterface public interface PersonBuilder { //定义一个方法,根据传递的姓名,创建Person对象返回 Person builderPerson(String name); } /* * 类的构造方法引用 * */ public class Demo { //定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象 public static void printName(String name,PersonBuilder pb){ Person person = pb.builderPerson(name); System.out.println(person.getName()); } public static void main(String[] args) { //调用printName方法,方法的参数PersonBuilder接口是一个函数式接口,可以传递Lambda printName("迪丽热巴",(String name)->{ return new Person(name); }); /* * 使用方法引用优化Lambda表达式 * 构造方法new Person(String name)已知 * 创建对象已知 new * 就可以使用Person引用new创建对象 * */ printName("古力娜扎",Person::new);//使用Person类的带参构造方法,通过传递的姓名创建对象 } }
数组的构造器引用:
/* * 定义一个创建数组的函数式接口 * */ @FunctionalInterface public interface ArrayBuilder { //定义一个创建int类型数组的方法,参数传递数组的长度,返回创建好的int类型数组 int[] builderArray(int length); } /* * 数组的构造器引用 * */ public class Demo { //定义一个方法,方法的参数传递创建数组的长度和ArrayBuilder接口 //方法内部根据传递的长度使用ArrayBuilder中的方法创建数组并返回 public static int[] creatArray(int len,ArrayBuilder ab){ return ab.builderArray(len); } public static void main(String[] args) { //调用createArray方法传递数组的长度和Lambda表达式 int[] arr1=creatArray(10,(len)->{ //根据数组的长度创建数组并返回 return new int[len]; }); System.out.println(arr1.length); /* * 使用方法引用优化Lambda表达式 * 已知创建的就是int[]数组 * 数组的长度也是已知的 * 就可以使用方法引用 * int[]引用new,根据参数传递的长度来创建数组 * */ int[] arr2 = creatArray(10, int[]::new); System.out.println(Arrays.toString(arr2)); System.out.println(arr2.length); } }