欢迎访问 生活随笔!

ag凯发k8国际

当前位置: ag凯发k8国际 > 编程语言 > java >内容正文

java

java方法的引用(打造lambda表达式的升级版) -ag凯发k8国际

发布时间:2024/10/14 java 24 豆豆
ag凯发k8国际 收集整理的这篇文章主要介绍了 java方法的引用(打造lambda表达式的升级版) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

1.初入方法引用
2.通过对象名引用成员方法
3.通过类名引用静态方法
4.通过super引用成员方法
5.通过this引用成员方法
6.类的构造器引用
7.数组的构造方法的引用

1.冗余的lambda表达式ag凯发k8国际的解决方案:
例子:

package untl1;public class myprint {public static void print(printable pri){pri.print("helloworld");}public static void main(string[] args) {print((str)->{system.out.println(str);});} } @functionalinterface interface printable{void print(string str); } 运行结果: helloworld

如果不懂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表达式的升级版)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得ag凯发k8国际网站内容还不错,欢迎将ag凯发k8国际推荐给好友。

网站地图