欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Guava 的 Function 接口

程序员文章站 2024-01-09 17:58:40
...

光是看一些博客容易打瞌睡,为此边记录边学习。

最近在研究 springfox 的源码,在其源码中多次看到了 Guava 的 Function 接口的使用,今天就来学习学习 Guava 的 Function 接口。


首先,需要搞明白的一个问题:什么是 Guava?

查阅博客得知,Guava 是对 Java API 的扩展,为 Java 中的一些常见 API 提供了更优雅的实现,Guava 中包含了 Google 正在其公司项目中使用的核心库。


要使用 Guava 库的 Function 接口,需要导入 Guava 依赖:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

回到主题,Function 接口。

首先来看一下这函数的源码:

@GwtCompatible
public interface Function<F, T> {
    @Nullable
    T apply(@Nullable F var1);

    boolean equals(@Nullable Object var1);
}

可以看到,这个接口提供了两个抽象方法,我们主要实现的是 apply 方法。

Function 接口是一个泛型接口,有两个泛型:F 和 T 。下面举个具体的例子,让一个类实现该接口,从而对比 F 和 T 的含义。

例如:

public class DateFormatFunction implements Function<Date, String> {
    @Override
    public String apply(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        return dateFormat.format(date);
    }
}

可以看到 F 其实是 apply 方法的形参的类型。T 是 apply 方法的返回值类型。


那么 Function 接口有哪些用处?Function 接口的用法是什么?

在这里,我们可以在 main 方法中,直接定义一个 Function 接口的匿名类,然后调用这个匿名类对象,例如:

public class Main {
    public static void main(String[] args) {
    
        Function<Date, String> function = new Function<Date, String>() {
            @Override
            public String apply(Date date) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
                return dateFormat.format(date);
            }
        };
        
        System.out.println(function.apply(new Date())); // output: 29/09/2021
        
    }
}

除了定义匿名类以外,还有一种方式,定义一个 Function 接口的实现类:

public class DateFormatFunction implements Function<Date, String> {
    @Override
    public String apply(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        return dateFormat.format(date);
    }
}

然后在 main 方法中使用该实现类:

public class Main {
    public static void main(String[] args) {
        DateFormatFunction function = new DateFormatFunction();
        System.out.println(function.apply(new Date()));
    }
}

也可以用多态的写法:

public class Main {
    public static void main(String[] args) {
        Function<Date, String> function = new DateFormatFunction();
        System.out.println(function.apply(new Date()));
    }
}

好,对于下面这个实现类,其实它的 apply 方法所做的事情就是将 Date 对象转化为 Date 格式化后的 String 对象,这体现出使用 Function 接口的一个好处:能够转换对象,并且隐藏具体的细节。

public class DateFormatFunction implements Function<Date, String> {
    @Override
    public String apply(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        return dateFormat.format(date);
    }
}

但对 Guava 的 Function 接口理解到这一步,这种理解太过于简单了,我觉得还不够。我想知道,在实际开发中如何使用 Function 接口,以及 Function 接口能为我们开发程序带来切切实实的好处是什么?

附带一提,这篇博客提到使用 Function 接口的一个优点是,可以使用依赖注入传递一个函数接口到一个类中,使得代码高内聚。但具体是怎么样的?我需要实际例子。

对于 Function 接口,据我目前所知,我们常用的是实现其 apply 方法,Function apply 所做的事情其实就是将一个对象转化为另一个对象,这也正符合函数(function)的特点:输入一些东西,经过函数处理,得到输出。但要注意,一个好功能,应当没有副作用,这就意味着一个对象传入 apply 方法后,应当是保持不变的。

有一种编程风格叫函数式编程,Guava 的 Function 接口使得在 Java 中进行函数式编程成为可能。

  • Java 的 API 库也提供了 Function 接口,在 java.util.function 包下,也得研究研究,看看其与
    Guava 的 Function 接口有什么区别。