文章目录

  • 前言
  • 方法引用的基本概念
  • 为什么可以使用方法引用?
  • 方法引用的分类
  • 2.1 静态方法引用
  • 2.2 实例方法引用
  • 2.3 特定类的任意对象的方法引用
  • 2.4 构造方法引用
  • 总结


前言

最近在学习开源项目的时候,发现了很多的双冒号操作符,比如

new Random().ints(10)
        .map(Math::abs)
        .forEach(System.out::println);

一直不太理解这是什么作用,为什么会有这个操作符,然后查找了一些资料供大家学习。

在Java中,双冒号(::)是一种新的操作符,被称为方法引用(Method Reference)。它是Java 8中引入的一个重要特性,旨在简化代码并提高可读性。方法引用允许开发人员直接通过名称来引用现有的方法,可以视为Lambda表达式的一种缩写。接下来我将详细介绍Java中双冒号操作符的作用,以及它在不同场景下的应用。

方法引用的基本概念

方法引用是在函数式编程中广泛应用的概念,它提供了一种简洁的语法来表示可以在某个上下文中执行的方法。在Java中,双冒号操作符用来引用方法,其使用方式是 在方法名称前加两个冒号(::)。通过方法引用,可以将方法作为参数进行传递。

例如,假设有一个接口:

interface Printer {
    void print(String value);
}

那么我们可以通过Lambda表达式来实现该接口:

Printer printer = (value) -> System.out.println(value);

这里,Lambda表达式(value) -> System.out.println(value)实现了接口的print方法。而方法引用的方式可以写作:

Printer printer = System.out::println;

这样,我们就直接引用了System.outprintln方法,使得代码更加简洁清晰。

为什么可以使用方法引用?

我感觉这是大部分人疑惑的地方,为什么有的可以使用方法引用有的时候不能使用方法引用呢?

其实,方法引用的场景是有限制的,简单来说就是,我们的函数式接口中的方法的签名应该和传入的方法的函数签名一致。

这里的函数签名特指参数列表返回值都相同,并且没有掺杂其他的额外逻辑

只有满足上述条件,才能进行转换,拿上面的例子举例。

Printer接口中的print方法参数是String,返回值是void

System.out.println(value)方法的参数和返回值和print方法相同,而且(value) -> System.out.println(value);这个表达式中没有任何其他的逻辑,只是执行System.out.println(value)方法,所以说两者签名相同,可以进行转换。

使用System.out::println;替换。

方法引用的分类

根据被引用方法的特性,方法引用可分为四种主要类型:静态方法引用、实例方法引用、特定类的任意对象的方法引用和构造方法引用。

2.1 静态方法引用

当要引用的方法是静态方法时,可以使用类名称来进行方法引用。比如,假设有一个静态方法:

class StringUtils {
    public static int toInt(String value) {
        return Integer.parseInt(value);
    }
}

可以使用双冒号操作符来引用该方法:

Function<String, Integer> parser = StringUtils::toInt;

这里,StringUtils::toInt表示引用StringUtils类的toInt方法。

2.2 实例方法引用

当要引用的方法是实例方法时,可以直接使用对象名或者使用类名来进行方法引用。比如,有一个实例方法:

class StringUtils {
    public int toInt(String value) {
        return Integer.parseInt(value);
    }
}

可以使用对象名或者类名来引用该方法:

StringUtils converter = new StringUtils();
Function<String, Integer> parser1 = converter::toInt;
Function<String, Integer> parser2 = StringUtils::toInt;

这里,converter::toIntStringUtils::toInt都表示引用 StringUtils类的toInt方法。

2.3 特定类的任意对象的方法引用

如果要引用的方法是实例方法,并且需要通过特定实例的对象来调用,可以使用特定类的任意对象的方法引用。这种方法引用形式是类似于调用静态方法的形式。比如,有一个实例方法:

class StringUtils {
    public int toInt(String value) {
        return Integer.parseInt(value);
    }
}

可以使用特定实例的对象来引用该方法:

Function<String, Integer> parser = StringUtils::toInt;

这里,StringUtils::toInt表示引用 StringUtils类的toInt方法。

2.4 构造方法引用

除了引用普通方法,方法引用还可以用来引用构造方法。在引用构造方法时,需要使用类的名称和new关键字。比如,有一个类:

class Person {
    private String name;

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

可以使用构造方法引用的方式创建对象:

Supplier<Person> personSupplier = Person::new;

这里,Person::new表示引用 Person 类的构造方法。

总结

总结一下,双冒号(::)操作符在Java中是方法引用的一种重要语法,通过它可以直接引用现有方法。方法引用可以分为静态方法引用、实例方法引用、特定类的任意对象的方法引用和构造方法引用四种类型,这些不同类型的方法引用在不同的场景下有着广泛的应用。通过方法引用,可以使得代码更加简洁、可读性更高,并且提高开发效率。希望这篇文章能帮助你更好地理解Java中双冒号操作符的作用。如果问题,请联系我改正。