Java8特性之方法引用

分类: Java

保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/14/ )。

1 概述

Java 8由Oracle公司于2014年3月18日发布,至今已过去数年之久。然而,直到今日仍有许多软件开发者对其相关特性不了解,这可能主要是Java教材更新缓慢的原因。为了使大家对与Java8的特性有全面系统的了解,本公众号将连续几篇文章介绍Java8中的各个特性。

Java8中新增的特性主要有:

  • Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。
  • 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  • 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
  • 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
  • Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
  • Date Time API − 加强对日期与时间的处理。
  • Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
  • Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

本文介绍其中的方法引用。其它特性会在后续文章中陆续介绍。

2 方法引用

2.1 概念

方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。

是不是没有看明白?没事的,我们举例子。

2.2 例子

举例子,我们有一个对象UserBean。

public class UserBean {
    private Integer id;
    private String name;

    public UserBean(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public static int compareById(UserBean a, UserBean b) {
        return a.id.compareTo(b.id);
    }
// 省略getter setter
}

然后对其进行排序:

public static void main(String[] args) {
        UserBean userBean01 = new UserBean(1,"a");
        UserBean userBean02 = new UserBean(2,"b");
        UserBean userBean03 = new UserBean(3,"c");
        List<UserBean> userBeanList = new ArrayList<>(Arrays.asList(userBean01,userBean03,userBean02));

        userBeanList.sort(UserBean::compareById);

        for (UserBean userBean: userBeanList) {
            System.out.println(userBean.getId() + ":" + userBean.getName());
        }
    }

这个时候我们发现:

userBeanList.sort(UserBean::compareById);

使用了方法引用。

那我会回溯一下,如果不使用方法引用,则应该:

userBeanList.sort(new Comparator<UserBean>() {
            @Override
            public int compare(UserBean o1, UserBean o2) {
                return o1.getId().compareTo(o2.getId());
            }
        });

因为sort中要传入的参数是Comparator的对象,因此我们要定义一个对象,而定义对象的时候,需要实现其中的抽象方法。于是就写了上面的一串,其实就是单单为了说明比较的方式。

这是我们可以看到,Comparator接口是一个函数式接口,我们可以使用lambda函数来指定它,因此可以简写为:

userBeanList.sort((a,b)-> a.getId().compareTo(b.getId()));

而这个操作,我们可以写到对象里,这样和对象写到一起结构比较合理和清晰。例如我们已经写了:

public static int compareById(UserBean a, UserBean b) {
        return a.id.compareTo(b.id);
    }

所以,可以修改为:

userBeanList.sort((a,b)-> UserBean.compareById(a,b));

其实我们使用lambda函数就是直接调用了一个方法。这时,我们可以直接简写为:

userBeanList.sort(UserBean::compareById);

因此,本质其实是采用lambda函数的方式实现了一个函数式接口,只不过实现的方式是另一个函数,我们只需要指定一下。

现在,再回去看方法引用的定义,就能够看明白了。

2.3 使用方法

方法引用的标准形式是:类名::方法名。(注意:只需要写方法名,不需要写括号)。有以下四种形式的方法引用:

  • 引用静态方法 ContainingClass::staticMethodName
  • 引用某个对象的实例方法 containingObject::instanceMethodName
  • 引用某个类型的任意对象的实例方法 ContainingType::methodName
  • 引用构造方法 ClassName::new

3 总结

Java8 提供的方法引用使得我们可以更为便捷地引用类、对象等处的方法。这能使得Java程序更为清晰、简介。

关于Java8中方法引用的介绍就到这里,在后续的文章中我们将介绍Java8中的其它特性。

可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。

作者书籍推荐

作者书籍推荐