Java Supplier和Consumer接口使用解读

 更新时间:2026年01月04日 15:09:03   作者:jpq+  
这篇文章介绍了Java中的Supplier和Consumer接口,它们都是函数式接口,可以用于Lambda表达式,Supplier接口用于延迟计算或生成值,而Consumer接口用于接受单一输入参数并且不返回任何结果的操作

Supplier

在Java中,Supplier接口是一个重要的函数式接口,它属于java.util.function包,Supplier通常用于延迟计算或生成值的场景。

Supplier接口是一个泛型接口,其get()方法不接受任何参数但返回一个泛型类型T的值。

这个接口被注解为@FunctionalInterface,表明它是一个函数式接口,可以用于Lambda表达式。

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

示例代码:

import java.util.Random;
import java.util.function.Supplier;

public class Main {
    public static void main(String[] args) {
        // 创建一个Supplier接口的实例,通过Lambda表达式实现get()方法来生成随机数
        Supplier<Integer> randomSupplier = () -> {
            Random random = new Random();
            return random.nextInt(100); // 生成0到99的随机数
        };

        int randomNumber = randomSupplier.get();
        System.out.println("随机数:" + randomNumber);
    }
}

Supplier接口的一个强大之处在于它支持惰性计算。这意味着生成值的计算只会在需要时才执行。

例如以下示例,其中我们使用Supplier来延迟计算字符串的长度:

String text = "Hello, World!";
Supplier<Integer> lengthSupplier = () -> text.length();

// 假设有一些其他耗时操作

int length = lengthSupplier.get();
System.out.println("字符串长度:" + length);

在某些情况下,可以使用Supplier接口来处理异常情况。

例如,如果一个方法可能会抛出异常,可以使用Supplier来封装这个方法,并在调用get()方法时捕获异常:

import java.util.function.Supplier;

public class SupplierWithExceptionHandling {
    public static void main(String[] args) {
        // 创建一个Supplier实例,其中包含可能抛出异常的操作
        Supplier<String> supplier = () -> {
            try {
                // 在这里执行可能会抛出异常的操作
                return "Hello, World!";
            } catch (Exception e) {
                // 处理异常情况
                return "An error occurred: " + e.getMessage();
            }
        };

        // 调用Supplier的get()方法,并处理可能的异常
        try {
            String result = supplier.get();
            System.out.println(result);
        } catch (Exception e) {
            // 如果Supplier内部的try-catch块没有处理异常,这里可以再次捕获并处理
            System.err.println("Error in Supplier: " + e.getMessage());
        }
    }
}

其中的lambda表达式包含了一个try-catch块。当调用supplier.get()时,它会尝试执行可能会抛出异常的操作,并在catch块中处理异常。

这样,即使Supplier内部的操作抛出了异常,程序仍然可以继续运行,并且可以根据需要处理异常情况。

Consumer

Consumer接口也是一个函数式接口,它表示一个接受单一输入参数并且不返回任何结果的操作。 你可以把它想象成一个消费者,你给它一个东西,它消费掉这个东西,但不给你任何回报。

Consumer接口在Java 8中定义如下:

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

}

Consumer接口中定义了一个accept方法,它接受一个泛型类型T的参数,并且没有返回值(void)。此外,它还提供了一个默认方法andThen,允许将多个Consumer串联起来,形成一个操作链。

使用示例,使用 Consumer 接口对集合中的元素进行求和操作:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 使用 AtomicInteger 来保存结果
AtomicInteger sum = new AtomicInteger();

Consumer<Integer> addToSum = num -> sum.addAndGet(num);

numbers.forEach(addToSum);

System.out.println("Sum: " + sum); // 输出 "Sum: 15"

条件执行: 可以使用filter方法来创建一个仅在满足特定条件时才执行操作的Consumer。这对于过滤集合中的元素非常有用:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Consumer<Integer> printEvenNumbers = n -> {
    if (n % 2 == 0) {
        System.out.println(n);
    }
};
numbers.forEach(printEvenNumbers);

异常处理: 可以使用try-catch块来处理Consumer中可能发生的异常。这可以确保即使发生错误,程序也不会崩溃:

Consumer<String> printLength = s -> {
    try {
        System.out.println(s.length());
    } catch (Exception e) {
        System.err.println("Error processing string: " + e.getMessage());
    }
};
printLength.accept("Hello, World!");

总结

  • Consumer 接口为函数式编程提供了重要的支持。通过使用 Consumer 接口,我们可以轻松地定义并执行一个接受一个参数并且不返回结果的操作。Consumer 接口特别适用于遍历集合或执行消费型操作。
  • Supplier接口提供了一种灵活而强大的机制来获取或生成数据,使用Supplier接口可以使代码更加灵活和易于维护,特别是在需要生成值或进行惰性计算的情况里。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java线程中的Timer和TimerTask原理详解

    Java线程中的Timer和TimerTask原理详解

    这篇文章主要介绍了Java线程中的Timer和TimerTask原理详解,Timer和TimerTask成对出现,Timer是定时器,TimerTask是定时任务,换句话说,定时任务TimerTask是给定时器Timer执行的具体任务,需要的朋友可以参考下
    2023-10-10
  • java List 排序之冒泡排序实例代码

    java List 排序之冒泡排序实例代码

    这篇文章主要介绍了java List 排序之冒泡排序实例代码的相关资料,需要的朋友可以参考下
    2017-05-05
  • Java代理模式的示例详解

    Java代理模式的示例详解

    代理模式(Proxy Parttern)为一个对象提供一个替身,来控制这个对象的访问,即通过代理对象来访问目标对象。本文将通过示例详细讲解一下这个模式,需要的可以参考一下
    2022-02-02
  • Springboot+jwt实现在线用户功能(示例代码)

    Springboot+jwt实现在线用户功能(示例代码)

    这篇文章主要介绍了Springboot+jwt实现在线用户功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-12-12
  • Spark SerializedLambda错误的两种解决方案

    Spark SerializedLambda错误的两种解决方案

    这篇文章主要介绍了Spark SerializedLambda错误的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Spring框架基于注解的AOP之各种通知的使用与环绕通知实现详解

    Spring框架基于注解的AOP之各种通知的使用与环绕通知实现详解

    这篇文章主要介绍了Spring框架基于注解的AOP之各种通知的使用及其环绕通知,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-11-11
  • executor包执行器功能

    executor包执行器功能

    这篇文章主要介绍了executor包执行器功能,executor包中的各个子包提供的功能,最终这些功能都由Executor接口及其实现类共同对外提供服务。下文介绍该执行功能,具有一定的参考价值,需要的朋友可以考一下
    2022-02-02
  • 深入了解Java I/O 之File类

    深入了解Java I/O 之File类

    这篇文章主要介绍了Java I/O深入学习之File和RandomAccessFile, I/O系统即输入/输出系统,对于一门程序语言来说,创建一个好的输入/输出系统并非易事。需要的朋友可以参考下
    2021-08-08
  • 使用MyBatis拦截器实现SQL的完整打印

    使用MyBatis拦截器实现SQL的完整打印

    当我们使用Mybatis结合Mybatis-plus进行开发时,为了查看执行sql的信息通常我们可以通过属性配置的方式打印出执行的sql语句,但这样的打印出了sql语句常带有占位符信息,不利于排错,所以本文介绍了构建MyBatis拦截器,实现SQL的完整打印,需要的朋友可以参考下
    2024-07-07
  • 提升性能秘密武器Java Unsafe类面试精讲

    提升性能秘密武器Java Unsafe类面试精讲

    这篇文章主要为大家介绍了提升性能秘密武器Java Unsafe类面试精讲,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10

最新评论