Java方法引用原理实例解析

网友投稿 275 2022-10-05


Java方法引用原理实例解析

目录冗余的Lambda场景问题分析用方法引用改进代码方法引用符通过对象名引用成员方法通过类名称引用静态方法通过super引用成员方法通过this引用成员方法类的构造器引用数组的构造器引用总结

在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。那么考虑 一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑?

冗余的Lambda场景

在 Printable 接口当中唯一的抽象方法 print 接收一个字符串参数,目的就是为了打印显示它。那么通过Lambda 来使用它的代码很简单:

public class Demo1 {

private static void printString(Printable data) {

data.print("Hello, World!");

}

public static void main(String[] args) {

printString(s -> System.out.println(s));

}

}

interface Printable {

void print(String str);

}

其中 printString 方法只管调用 Printable 接口的 print 方法,而并不管 print 方法的具体实现逻辑会将字符串打印到什么地方去。而 main 方法通过Lambda表达式指定了函数式接口 Printable 的具体操作方案为:拿到 String(类型可推导,所以可省略)数据后,在控制台中输出它。

问题分析

这段代码的问题在于,对字符串进行控制台打印输出的操作方案,明明已经有了现成的实现,那就是 System.out 对象中的 println(String) 方法。既然Lambda希望做的事情就是调用 println(String) 方法,那何必自己手动调用呢?

用方法引用改进代码

能否省去Lambda的语法格式(尽管它已经相当简洁)呢?只要“引用”过去就好了:

public class Demo2 {

private static void printString(Printable data) {

data.print("Hello, World!");

}

public static void main(String[] args) {

printString(System.out::println);

}

}

请注意其中的双冒号 :: 写法,这被称为“方法引用”,而双冒号是一种新的语法。

方法引用符

双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

语义分析:

例如上例中, System.out 对象中有一个重载的 println(String) 方法恰好就是我们所需要的。那么对于 printString 方法的函数式接口参数,对比下面两种写法,完全等效:

Lambda表达式写法: s -> System.out.println(s);

方法引用写法: System.out::println

第一种语义是指:拿到参数之后经Lambda之手,继而传递给 System.out.println 方法去处理。

第二种等效写法的语义是指:直接让 System.out 中的 println 方法来取代Lambda。

两种写法的执行效果完全一样,而第二种方法引用的写法复用了已有方案,更加简洁。

注:Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常

通过对象名引用成员方法

public class Demo3 {

private static void printString(printable lambda) {

lambda.print("Hello");

}

public static void main(String[] args) {

MethodRefObject obj = new MethodRefObject();

printString(obj::printUpperCase);

}

}

@FunctionalInterface

interface printable {

void print(String str);

}

class MethodRefObject {

public void printUpperCasehttp://(String str) {

System.out.println(str.toUpperCase());

}

}

通过类名称引用静态方法

public class Demo4 {

private static void method(int num, Calcable lambda) {

System.out.println(lambda.calc(num));

}

public static void main(String[] args) {

method(-10, Math::abs);

}

}

@FunctionalInterface

interface Calcable {

int calc(int num);

}

通过super引用成员方法

public class Demo5 extends Human{

@Override public void sayHello() {

System.out.println("大家好,我是Man!");

}

//定义方法method,参数传递Greetable接口

public void method(Greetable g){

g.greet();

}

public void show(){

method(super::sayHello);

}

}

class Human {

public void sayHello() {

System.out.println("Hello!");

}

}

@FunctionalInterface

interface Greetable {

void greet();

}

通过this引用成员方法

public class Demo6 {

private void buyHouse() {

System.out.println("买房子");

}

private void marry(Richable lambda) {

lambda.buy();

}

public void beHappy() {

marry(() -> this.buyHouse());

}

}

@FunctionalInterface

interface Richable {

void buy();

}

类的构造器引用

public class Demo7 {

public static void printName(String name, PersonBuilder builder) {

System.out.println(builder.buildPerson(name).getName());

}public static void main(String[] args) {

printName("赵丽颖", Person::new);

}

}

class Person{

String name;

public Person(String name) {

this.name = name;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

'}';

}

}

interface PersonBuilder {

Person buildPerson(String name);

}

数组的构造器引用

public class Demo8 {

private static int[] initArray(int length, ArrayBuilder builder) {

return builder.buildArray(length);

}

public static void main(String[] args) {

int[] array = initArray(10, int[]::new);

}

}

@FunctionalInterface

interface ArrayBuilder {

int[] buildArray(int length);

}

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Meris 僵尸网络利用 HTTP 管道来粉碎 DDoS 攻击记录(meris眼膜)
下一篇:DDoS 变得更大、更智能、更多样化(ddos高防ip)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~