欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > java >内容正文

java

Java方法的引用(打造Lambda表达式的升级版)

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

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

1.初入方法引用

1.冗余的Lambda表达式解决方案:
例子:

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的替代者

2.通过对象名引用成员方法

其实和上边的例子差不多再来一个例子:

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的替代者

3.通过类名引用静态方法

我们分别用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

4.通过super引用成员方法

如果存在继承关系,当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

其实和对象引用方法名一样的

5.通过this引用成员方法

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的儿子

6.类的构造器的引用

由于构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称::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); } 运行结果: 哈哈

7.数组的构造器引用

数组也是 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

总结

以上是生活随笔为你收集整理的Java方法的引用(打造Lambda表达式的升级版)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。