java方法的引用(打造lambda表达式的升级版) -ag凯发k8国际
1.初入方法引用
2.通过对象名引用成员方法
3.通过类名引用静态方法
4.通过super引用成员方法
5.通过this引用成员方法
6.类的构造器引用
7.数组的构造方法的引用
1.冗余的lambda表达式ag凯发k8国际的解决方案:
例子:
如果不懂lambda可以参照这一篇博客:lambda表达式详解
分析上边的代码;
其中 prin 方法只管调用 printable 接口的 print 方法,而并不管 print 方法的具体实现逻辑会将字符串 打印到什么地方去。而 main 方法通过lambda表达式指定了函数式接口 printable 的具体操作方案为:拿到 string(类型可推导,所以可省略)数据后,在控制台中输出它。这段代码的问题在于,对字符串进行控制台打印输出的操作方案,明明已经有了现成的实现,那就是 system.out 对象中的 println(string) 方法。既然lambda希望做的事情就是调用 println(string) 方法,那何必自己手动调 用呢
啥意思呢看用方法引用的例子:
package untl1; public class myprint {public static void print(printable pri){pri.print("helloworld");}public static void main(string[] args) {print(system.out::println);} } @functionalinterface interface printable{void print(string str); } 运行结果: helloworld卧槽,这么高级
下面是对上边代码的解释:
1.请注意其中的双冒号::写法,这被称为“方法引用”,而双冒号是一种新的语法,双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果lambda要表达的函数方案已经存在于某个方 法的实现中,那么则可以通过双冒号来引用该方法作为lambda的替代者。
2.例如上例中, system.out 对象中有一个重载的 println(string) 方法恰好就是我们所需要的。那么对于 printstring 方法的函数式接口参数,对于上边的两种写法是等效的
对于例子中两种写法的对比:
写法类型格式语义lambda表达式 | s -> system.out.println(s); | 拿到参数之后经lambda之手,继而传递给 system.out.println 方法去处理。 |
方法引用 | system.out::println | 直接让 system.out 中的 println 方法来取代lambda。两种写法的执行效果完全一 样,而第二种方法引用的写法复用了已有方案,更加简洁。 注:lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常 |
如果使用lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式——它们都 将被自动推导。而如果使用方法引用,也是同样可以根据上下文进行推导。 函数式接口是lambda的基础,而方法引用是lambda的孪生兄弟
上述的第二个例子就是把已经存在的system.out这个对象通过已经存在的printfln这个方法
再细品这句话:如果lambda要表达的函数方案已经存在于某个方 法的实现中,那么则可以通过双冒号来引用该方法作为lambda的替代者。
其实和上边的例子差不多再来一个例子:
package untl1; public class myprint {public void printstring(string str){system.out.println(str.touppercase());}public static void prin(printable pri){pri.print("helloworld");}public static void main(string[] args) {myprint p=new myprint();prin(p::printstring);}} @functionalinterface interface printable{void print(string str); } 运行结果: helloworld你品你细品:如果lambda要表达的函数方案已经存在于某个方 法的实现中,那么则可以通过双冒号来引用该方法作为lambda的替代者。
我们分别用lambda表达式和方法引用来举例对比,求一个数的绝对值,然和再输出
用lambda表达式:
package untl1; public class myprint {public static void aaa(int num,printabs pri){system.out.println(pri.aboutabs(num));}public static void main(string[] args) {aaa(-100,num->math.abs(num));} } @functionalinterface interface printabs{int aboutabs(int a); } 输出结果: 100用方法的引用:
package untl1; public class myprint {public static void aaa(int num,printabs pri){system.out.println(pri.aboutabs(num));}public static void main(string[] args) {aaa(-100,math::abs);} } @functionalinterface interface printabs{int aboutabs(int a); } 输出结果: 100如果存在继承关系,当lambda中需要出现super调用时,也可以使用方法引用进行替代。
废话不多说,先用lambda举例子:
package untl1; public class myprint extends human{public void sayhello(){system.out.println("hello我是human的儿子");}public void method(greetable g){g.greet();}public void show(){method(()->{human h=new human();h.sayhello();});}public static void main(string[] args) {myprint p=new myprint();p.show();} }class human{public void sayhello(){system.out.println("hello,我是human");} } @functionalinterface interface greetable{void greet(); } 运行结果: hello,我是human那么上边的代码用方法的引用:
package untl1; public class myprint extends human{public void sayhello(){system.out.println("hello我是human的儿子");}public void method(greetable g){g.greet();}public void show(){method(super::sayhello);}public static void main(string[] args) {myprint p=new myprint();p.show();} }class human{public void sayhello(){system.out.println("hello,我是human");} } @functionalinterface interface greetable{void greet(); } 运行结果: hello,我是human其实和对象引用方法名一样的
this代表当前对象,如果需要引用的方法就是当前类中的成员方法,那么可以使用“this::成员方法”的格式来使用方法
package untl1; public class myprint extends human{public void sayhello(){system.out.println("hello我是human的儿子");}public void method(greetable g){g.greet();}public void show(){method(this::sayhello);}public static void main(string[] args) {myprint p=new myprint();p.show();} }class human{public void sayhello(){system.out.println("hello,我是human");} } @functionalinterface interface greetable{void greet(); } 输出结果: hello我是human的儿子由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称::new 的格式表示
例子(lambda表达式):
package untl1; public class person {private string name;public person(string name) {this.name = name;}public string getname() {return name;}public void setname(string name) {this.name = name;}public static void printname(string name,personbuilder per){system.out.println(per.buildperson(name).getname());}public static void main(string[] args) {printname("哈哈",name->new person(name));} } interface personbuilder {person buildperson(string name); } 运行结果: 哈哈用类构造器的引用:
package untl1; public class person {private string name;public person(string name) {this.name = name;}public string getname() {return name;}public void setname(string name) {this.name = name;}public static void printname(string name,personbuilder per){system.out.println(per.buildperson(name).getname());}public static void main(string[] args) {printname("哈哈",person::new);} } interface personbuilder {person buildperson(string name); } 运行结果: 哈哈数组也是 object 的子类对象,所以同样具有构造器,只是语法稍有不同
例子:
package untl1; public class person {public static int[] createarray(int length,arraybuild ab){return ab.builderarray(length);}public static void main(string[] args) {// int arr[]=createarray(10,len->new int[len]);int arr[]=createarray(10,int[]::new);system.out.println(arr.length);} } interface arraybuild{int [] builderarray(int length); } 运行结果: 10总结
以上是ag凯发k8国际为你收集整理的java方法的引用(打造lambda表达式的升级版)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: java函数式接口看这一篇就够了
- 下一篇: java资深反射玩家