方法引用符
既然标题是方法引用符,什么是方法引用符呢?方法引用符就是双冒号【::】,这就是方法引用,而这也是一种新语法,是一种引用运算符,方法引用就是通过它来实现的。如果Lambda要表达的函数方案已经存在于某个方法的实现中,我们就可以通过双冒号来引用该方法实现对Lambda的代替。
如何使用方法引用?
方法引用可以通过以下几方面来使用:
既然是有以上几种方式的方法引用,那我们接下来就逐一进行学习一下吧。
通过对象名引用成员方法
例如:
定义一个成员方法,传递字符串,把字符串按照大写输出
我们把上面的需求来实现一下吧。
先定义一个类
public class Demo02MethodRerObject {//定义一个成员方法,传递字符串,把字符串按照大写输出public void printUpperCaseString(String s){System.out.println(s.toUpperCase());}}
既然是输出我们就需要打印出来,而用Lambdab就需要我们定义一个打印的函数式接口,在函数式接口中定义打印字符串的抽象方法。
/*定义一个打印的函数式接口*/@FunctionalInterfacepublic interface Printable {//定义打印字符串的抽象方法void print(String s);}
而通过对象名引用成员方法,使用前提是对象名已经存在的,成员方法也是存在的,就可以使用对象名来引用成员方法。下面我们用代码写一下:首先我们用Lambda来写一下这个需求,然后再进行用方法引用优化Lambda。
public class Demo03ObjectMethodReference {//定义一个方法,方法参数传递Printable接口public static void pringString(Printable p){p.print("abcde");}public static void main(String[] args) {//pringString(System.out::print);//调用printString方法,方法的参数pringable是一个函数式接口,所以可以传递LambdapringString((s)->{//创建MethodRerObject对象Demo02MethodRerObject methodRerObject=new Demo02MethodRerObject();//调用Demo02MethodRerObject对象中的成员方法printUpperCaseString,把字符串按照大写输出methodRerObject.printUpperCaseString(s);});/*使用方法引用优化Lambda对象已经存在Demo02MethodRerObject成员方法也是已经存在的printUpperCaseString所以我们可以使用对象名引用成员方法*/Demo02MethodRerObject methodRerObject=new Demo02MethodRerObject();pringString(methodRerObject::printUpperCaseString);}}
通过类名引用静态方法
这次我们定义一个方法,方法的参数传递计算绝对值的整数和函数式接口Calcable。
先来定义一个接口
@FunctionalInterfacepublic interface Calcable {//定义一个抽象方法,传递一个整数,对整数进行绝对值计算并返回int AbsCals(int number);}
通过类名引用静态成员方法,前提是类已经存在,静态成员方法也已经存在,就可以通过类名直接引用静态成员方法。我们同样先创建类,定义方法,用Lambda编写代码,之后用方法引用优化。
public class Demo04StaticMethodReference {//定义一个方法,方法的参数传递计算绝对值的整数和函数式接口Calcablepublic static int method1(int number,Calcable c){return c.AbsCals(number);}public static void main(String[] args) {//调用method方法,传递计算绝对值的整数和lambda表达式int number=method1(-10,(n)->{//对参数进行绝对值计算并返回结果return Math.abs(n);});System.out.println(number);/*使用方法引用优化Lambdab表达式Math类是存在的abs计算绝对值的静态方法也是存在的所以我们可以直接通过类名引用静态方法*/int number2=method1(-10, Math::abs);System.out.println(number2);}}
通过super引用成员方法
定义一个见面的方法
我们使用子父类见面打招呼的方法进行演示
同样这次我们定义见面的函数式接口
/*定义见面的函数式接口*/@FunctionalInterfacepublic interface Greetable {//定义一个见面的方法void greet();}
既然需要继承我们定义一个父类
/*定义父类方法*/public class Demo05Fu_Human {//定义一个sayHello的方法public void sayHello(){System.out.println("Hello! 我是Human。");}}
再定义一个子类,在子类中出现父类的成员方法,先使用Lambda编写代码,再进行方法引用优化。
使用super引用父类的成员方法,前提super是已经存在的,父类的成员方法也是存在的,就可以直接使用super引用父类成员方法。
import java.nio.channels.ShutdownChannelGroupException;/*定义子类*/public class Demo06Zi_Man extends Demo05Fu_Human {//子类重写父类sayHello方法@Overridepublic void sayHello() {System.out.println("Hello!我是Man。");}//定义一个方法,参数传递Gerrtable接口public void method(Greetable g){g.greet();}public void show(){//调用method方法,方法参数Greetable是一个函数式接口,所以可以传递Lambda表达式method(()->{//创建父类的Human对象Demo05Fu_Human fHuman=new Demo05Fu_Human();fHuman.sayHello();});//因为有子父类关系,所以存在的一个关键super,代表父类,可以直接使用super调用父类的成员方法method(()->{super.sayHello();});/*使用super引用类的成员方法super是已经存在的父类的成员方法也是存在的使用可以直接使用super引用父类成员方法*/method(super::sayHello);}public static void main(String[] args) {//调用show方法new Demo06Zi_Man().show();}}
通过this引用成员方法
示例:
定义一个买房子的方法
同样,首先定义函数式接口。
/*定义一个富有的函数式接口*/@FunctionalInterfacepublic interface Richable {//定义一个想买什么就买什么的方法void buy();}
然后怎么创建类,再定义买房子的方法。通过this引用成员方法,前提this是已经存在的,买房子的成员方法也是存在的,就可以直接使用this引用成员方法。同样先使用Lambda编写代码,再进行方法引用优化。
/*通过this引用本类的成员方法*/public class Demo07_Husband {//定义一个买房子的方法public void buyHouse(){System.out.println("北京二环内买一套四合院!");}//定义一个结婚的方法,参数传递Richable接口public void marry(Richable r){r.buy();}//定义一个高兴的方法public void soHappy(){//调用结婚的方法,方法的参数Richable是一个函数式接口,传递Lambda表达式marry(()->{//使用this,成员方法,调用本类买房子的方法this.buyHouse();});/*使用方法引用优化Lambdathis是已经存在的买房子的成员方法也是存在的可以直接使用this引用成员方法*/marry(this::buyHouse);}public static void main(String[] args) {new Demo07_Husband().soHappy();}}
类的构造器引用
定义一个Person类。
/*person类*/public class Person {private String name;public Person() {super();// TODO Auto-generated constructor stub}public Person(String name) {super();this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
然后创建一个Person对象的函数式接口
*定义一个创建erson对象的函数式接口*/@FunctionalInterfacepublic interface PersonBuilder {//定义一个方法,根据传递的姓名,创建person对象返回Person buliderPerson(String name);}
再传递一个方法,参数传递姓名和PersonBulider接口,方法中通过 姓名创建Person对象。类的构造器引用,前提构造方法new Person(String name)已知,创建对象已知 new,就可以使用Person引用new创建对象。同样先使用Lambda编写代码,再进行方法引用优化。
/*类的构造器(构造方法)引用*/import java.time.chrono.MinguoChronology;import javax.print.attribute.standard.PrinterName;public class Demo08Person {//传递一个方法,参数传递姓名和PersonBulider接口,方法中通过 姓名创建Person对象public static void printName(String name,PersonBuilder pb){Person person=pb.buliderPerson(name);System.out.println(person.getName());}public static void main(String[] args) {//调用printName方法,方法的参数传递了函数式接口,我们可以使用Lambda表达式printName("张三",(name)->{return new Person(name);});/*使用方法引用优化Lambda表达式构造方法new Person(String name)已知创建对象已知 new就可以使用Person引用new创建对象*/printName("痛而不言笑而不语的浅伤",Person::new);}}
数组的构造器引用
同样,先创建一个数组的函数式接口
/*定义一个创建数组的函数式接口*/@FunctionalInterfacepublic interface ArrayBulider {// 定义一个int类型的数组方法,参数传递数组的长度,返回创建好的int类型的数组int[] buliderArray(int length);}
方法的参数传递创建数组的长度和ArrayBulider接口,方法内部根据创建的长度使用ArrayBuilder中的方法创建数组并返回。前提,已知创建的就是int[]数组,数组的长度也是已知的,就可以通过数组int[]引用new,根据参数传递的长度来创建数组同样先使用Lambda编写代码,再进行方法引用优化。
import java.lang.reflect.Array;import java.util.Arrays;/*数组的构造器引用*/public class Demo09Array_BuilderArray {/*定义一个方法方法的参数传递创建数组的长度和ArrayBulider接口方法内部根据创建的长度使用ArrayBuilder中的方法创建数组并返回*/public static int[] arrayLength(int length,ArrayBulider ab){return ab.buliderArray(length);}public static void main(String[] args) {//调用arrayLength方法、传递数组的长度和Lambda表达式int[]arr=arrayLength(10,(len)->{return new int[len];});System.out.println(arr.length);/*使用方法引用优化Lambda表达式已知创建的就是int[]数组数组的长度也是已知的就可以通过数组int[]引用new,根据参数传递的长度来创建数组*/int[]arr1=arrayLength(5, int[]::new);System.out.println(arr1.length);System.out.println(Arrays.toString(arr1));}}
《java视频教学》