Java 之方法引用:让代码更简洁优雅

大家好!今天我们来聊聊 Java 中一个非常有用的特性:方法引用。它可以让我们写出更简洁、更易读的代码。

1. 为什么需要方法引用?

在介绍方法引用之前,让我们先看看 Java 中以前如何实现类似的功能,以及它们存在的不足。

1.1 匿名内部类

匿名内部类可以让我们在需要时定义一个类的实例,而无需为它命名。它经常被用来实现接口或扩展抽象类。

interface MyInterface {
    void operate(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = new MyInterface() {
            @Override
            public void operate(int a, int b) {
                System.out.println(a + b);
            }
        };
        myInterface.operate(2, 3); // 输出 5
    }
}

在这个例子中,我们定义了一个接口 MyInterface,它有一个 operate 方法。在 main 方法中,我们创建了一个匿名内部类,它实现了 MyInterface 接口,并重写了 operate 方法。

缺点:

  • 代码冗长,可读性差。

  • 需要定义一个额外的类,增加了代码的复杂度。

1.2 Lambda 表达式

Lambda 表达式是一种更简洁的语法,它可以用来表示匿名函数。

interface MyInterface {
    void operate(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = (a, b) -> System.out.println(a + b);
        myInterface.operate(2, 3); // 输出 5
    }
}

在这个例子中,我们使用 lambda 表达式 (a, b) -> System.out.println(a + b) 来实现 MyInterface 接口的 operate 方法。

缺点:

  • 当 lambda 表达式只包含一个方法调用时,代码仍然显得有些冗长。

1.3 方法引用

为了解决匿名内部类和 lambda 表达式存在的缺点,Java 引入了方法引用。它可以让我们用更简洁的方式来表示 lambda 表达式,让代码更易读。

2. 什么是方法引用?

方法引用,顾名思义,就是将方法作为参数传递给另一个方法。它本质上是一种语法糖,可以让我们用更简洁的方式来表示 lambda 表达式。

好处:

  • 代码更简洁:方法引用可以避免冗长的 lambda 表达式,让代码更易读。

  • 更易理解:方法引用更直观地表达了代码的意图,更容易理解。

使用场景:

  • 当 lambda 表达式只包含一个方法调用时,可以使用方法引用。

  • 当需要传递一个方法作为参数给另一个方法时,可以使用方法引用。

使用方法引用条件:

  • 方法的参数列表必须与被引用的方法的参数列表相同。

  • 方法的返回类型必须与被引用的方法的返回类型相同。

表示符号:

方法引用使用双冒号 (::) 符号来表示。

3. 引用静态方法

概念说明:

我们可以使用方法引用来引用一个类的静态方法。

引用方法:

类名::静态方法名

引用格式:

interface MyInterface {
    int operate(int a, int b);
}

public class Main {
    public static int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        MyInterface myInterface = Main::add; // 使用方法引用引用静态方法
        int result = myInterface.operate(2, 3);
        System.out.println(result); // 输出 5
    }
}

案例演示:

在这个例子中,我们定义了一个接口 MyInterface,它有一个 operate 方法。然后我们定义了一个类 Main,它包含一个静态方法 add。在 main 方法中,我们使用方法引用 Main::add 来引用 add 方法,并将它赋值给 myInterface 变量。最后,我们调用 myInterface.operate(2, 3),它会调用 add 方法,并将结果打印出来。

4. 引用成员方法

概念说明:

我们可以使用方法引用来引用一个对象的成员方法。(局限性:不能引用所有类中的成员方法)

引用方法:

            1.其它类:其它类对象::方法名
            2.本类:this::方法名(非静态) &&  若是静态  =>  new 类名()::方法名
            3.父类:super::方法名

引用格式:

interface MyInterface {
    String operate(String str);
}

public class Main {
    public String toUpperCase(String str) {
        return str.toUpperCase();
    }

    public static void main(String[] args) {
        Main main = new Main();
        MyInterface myInterface = main::toUpperCase; // 使用方法引用引用成员方法
        String result = myInterface.operate("hello");
        System.out.println(result); // 输出 HELLO
    }
}

案例演示:

在这个例子中,我们定义了一个接口 MyInterface,它有一个 operate 方法。然后我们定义了一个类 Main,它包含一个成员方法 toUpperCase。在 main 方法中,我们创建一个 Main 对象,并使用方法引用 main::toUpperCase 来引用 toUpperCase 方法,并将它赋值给 myInterface 变量。最后,我们调用 myInterface.operate("hello"),它会调用 toUpperCase 方法,并将结果打印出来。

5. 引用构造方法

概念说明:

我们可以使用方法引用来引用一个类的构造方法。

引用方法:

类名::new

引用格式:

interface MyInterface {
    Person create(String name);
}

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = Person::new; // 使用方法引用引用构造方法
        Person person = myInterface.create("John");
        System.out.println(person.name); // 输出 John
    }
}

案例演示:

在这个例子中,我们定义了一个接口 MyInterface,它有一个 create 方法。然后我们定义了一个类 Person,它有一个构造方法。在 main 方法中,我们使用方法引用 Person::new 来引用 Person 的构造方法,并将它赋值给 myInterface 变量。最后,我们调用 myInterface.create("John"),它会调用 Person 的构造方法,创建一个 Person 对象,并将结果打印出来。

6. 引用数组的构造方法

概念说明:

我们可以使用方法引用来引用一个数组的构造方法。

引用方法:

类型[]::new

引用格式:

interface MyInterface {
    int[] create(int length);
}

public class Main {
    public static void main(String[] args) {
        MyInterface myInterface = int[]::new; // 使用方法引用引用数组构造方法
        int[] array = myInterface.create(5);
        System.out.println(array.length); // 输出 5
    }
}

案例演示:

在这个例子中,我们定义了一个接口 MyInterface,它有一个 create 方法。在 main 方法中,我们使用方法引用 int[]::new 来引用 int 数组的构造方法,并将它赋值给 myInterface 变量。最后,我们调用 myInterface.create(5),它会创建一个长度为 5 的 int 数组,并将结果打印出来。

7. 方法引用小demo

这里提供两个关于方法引用的小demo,分别展示了引用静态方法和引用成员方法的应用场景。

Demo 1:引用静态方法

这个demo展示了如何使用方法引用来简化代码,避免冗长的lambda表达式。

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class MethodReferenceDemo1 {

    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用lambda表达式
        names.forEach(name -> System.out.println(name.toUpperCase()));

        System.out.println("--------------------");

        // 使用方法引用
        names.forEach(String::toUpperCase);
    }
   
}

在这个例子中,我们使用 forEach 方法来遍历 names 列表中的每个元素。

  • 第一种方法使用 lambda 表达式 name -> System.out.println(name.toUpperCase()) 来将每个名字转换为大写并打印出来。

  • 第二种方法使用方法引用 String::toUpperCase 来引用 String 类的 toUpperCase 方法,实现同样的功能,代码更加简洁。

Demo 2:引用成员方法

这个demo展示了如何使用方法引用来引用对象的方法,并将其作为参数传递给另一个方法。

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

public class MethodReferenceDemo2 {

    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用lambda表达式
        Function<String, Integer> lengthFunction = name -> name.length();
        names.forEach(name -> System.out.println(lengthFunction.apply(name)));

        System.out.println("--------------------");

        // 使用方法引用
        names.forEach(name -> System.out.println(name.length()));
    }
}

在这个例子中,我们使用 forEach 方法来遍历 names 列表中的每个元素,并打印每个名字的长度。

  • 第一种方法使用 lambda 表达式 name -> name.length() 来获取每个名字的长度。

  • 第二种方法使用方法引用 name::length 来直接引用 String 类的 length 方法,实现同样的功能,代码更加简洁。

结语:希望能够帮助各位看官理解 Java 中的方法引用,并能够在你的代码中灵活地使用它。感谢各位看官的观看,下期见,谢谢~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值