java中的Supplier和Consumer类以及函数式编程,@Nullable注解使用练习

本文深入解析了Java中Supplier和Consumer接口的功能与应用,通过具体示例展示了如何使用这两个接口进行对象提供与消费操作,同时对比了传统写法与函数式编程的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Supplier和Consumer

Supplier提供者,跟Consumer类相反,Supplier类用于提供对象,它只有一个get方法,是一个抽象方法,需要编程者自定义想要返回的对象。

Consumer消费者,意即通过传递进一个参数来对参数进行操作。
accept方法用来对输入的参数进行自定义操作,因为是个抽象方法,所以需要实例化对象的时候进行Override

正常式写法:

import java.util.function.Consumer;
import java.util.function.Supplier;

public class Test {

    public static void main(String args[]){
        new Test().printSupplier(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return 666;
            }
        });

        new Test().printComsumer(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
               integer= integer+9999;
                System.out.println(integer);
            }
        });
    }
    public void printSupplier(Supplier<Integer> supplier){System.out.println(supplier.get());}

    public void printComsumer(Consumer<Integer> consumer){
        int a=1;
        consumer.accept(a);
    }
}

打印结果:

666
10000

函数式编程写法

public class Test {

    public static void main(String args[]){
        new Test().printSupplier(()->{return 666;});

        new Test().printComsumer((Integer integer)->{System.out.println(integer+999);});
        //new Test().printComsumer((integer)->{System.out.println(integer+999);});
    }
    public void printSupplier(Supplier<Integer> supplier){System.out.println(supplier.get());}

    public void printComsumer(Consumer<Integer> consumer){
        int a=1;
        consumer.accept(a);
    }
}

spring中的@Nullable注解

使用时需要引入jar包

 <dependency>
          <groupId>com.google.code.findbugs</groupId>
          <artifactId>findbugs</artifactId>
          <version>3.0.1</version>
 </dependency>

转自: https://blog.youkuaiyun.com/weixin_34343308/article/details/91432758

可标注于作用于方法参数,方法返回值,成员变量,属性上

参数可为null

public static boolean isBlank(@Nullable final CharSequence cs) {
    return !StringUtils.hasText(cs);
}

返回值可为null

@Nullable
public static String getCookieVal(HttpServletRequest request, String name) {
    Cookie cookie = getCookie(request, name);
    return cookie != null ? cookie.getValue() : null;
}

属性可为null

@Nullable
private String msg;

例如

public interface Hi {
@Nullable
public Integer b();
}

public class K implements Hi {
@Override
public Integer b() {
System.out.println(“haha”);
return null;
}
}

<think>我们正在解决一个Java编程问题:当调用`accept`方法时,如果返回值为空(null)会导致抛出异常。我们需要分析这个问题并提供解决方案。根据问题描述,我们推测可能是使用Java中的函数式接口(如`Consumer`或某个自定义函数式接口)的`accept`方法,并且在该方法的实现中返回了值,但实际上该函数式接口的`accept`方法返回型是`void`(即不返回任何值)。或者,可能是在使用`Method`对象进行反射调用时,遇到了返回值为null的情况,但调用者期望非空值。然而,在Java标准库中,常见的函数式接口的`accept`方法:-`Consumer`接口的`accept`方法返回型是`void`,所以它不应该有返回值。如果尝试返回一个值,编译器会报错。-如果是自定义的函数式接口,可能定义了一个非void返回型的`accept`方法,那么当返回null时,调用者如果期望非空值,就可能抛出异常(如空指针异常)。另外,问题也可能出现在方法引用(MethodReference)上。方法引用有几种形式,其中一种可能引用了返回值为null的方法,而调用者期望非空值。我们注意到用户提供的引用[1]中提到了方法引用,包括构造器引用(`ArrayList::new`),但并没有直接与`accept`方法抛出异常相关的内容。因此,我们需要更具体地分析问题场景。可能的情况:1.使用`Consumer`的`accept`方法,但传入的方法引用或Lambda表达式返回了值(而它不应该返回值)。2.使用`Function`或`Supplier`等函数式接口,当返回值为null时,后续使用这个返回值(如调用其方法)导致空指针异常。3.反射调用:使用`Method`对象的`invoke`方法,返回值为null,但调用者期望非空值,从而在后续操作中抛出空指针异常。由于问题描述中提到了“accept方法”,我们首先考虑函数式接口中的`accept`方法。在Java中,名为`accept`的方法主要在以下接口中:-`java.util.function.Consumer<T>`:`voidaccept(Tt)`-`java.util.function.BiConsumer<T,U>`:`voidaccept(Tt,Uu)`这些方法的返回型都是`void`,所以它们本身不会返回任何值,包括null。因此,如果调用这些接口的`accept`方法,不可能因为返回值为空而报错。那么,问题可能出现在其他地方。用户可能是指某个特定库中的`accept`方法?或者是指反射中的`Method`的`invoke`方法?但用户明确提到了“accept”。另外,用户提到“因返回值为空导致的报错”,这通常发生在有返回值的方法返回了null,而调用者没有做空值检查,直接使用了返回值,导致空指针异常。重新思考:用户可能误用了方法名?或者是指事件处理中的`accept`方法?考虑到用户之前的问题(引用[1])是关于方法引用的,我们推测用户可能在方法引用或Lambda表达式中遇到了问题。另一种可能性:用户在使用`Optional`时,调用了`ifPresent`方法(它接受一个`Consumer`),在`Consumer`中进行了某些操作,而这些操作中又调用了可能返回null的方法,导致空指针异常。但这并不是`accept`方法抛出异常,而是在`accept`方法内部执行时抛出的。因此,我们需要用户提供更具体的代码示例。但既然用户没有提供,我们只能根据常见情况给出建议。常见解决方案:1.如果是在函数式编程中,确保在返回值为null的情况下进行适当的处理(如使用`Optional`避免空指针)。2.在反射调用中,对返回结果进行空值检查。3.如果是自定义的函数式接口,考虑修改接口定义或检查实现中是否返回了null。由于问题描述不够具体,我们给出一个通用的建议:检查调用`accept`方法的上下文,确保在可能返回null的情况下,对返回值进行空值检查,或者确保传入的方法引用或Lambda表达式不会返回null(如果要求非空)。此外,用户可能指的是在使用方法引用时,被引用的方法返回了null,而调用者期望非空,导致后续操作出现空指针异常。例如:```javaFunction<String,String>func=String::toUpperCase;//假设toUpperCase可能返回null(实际上不会,这里只是举例)Stringresult=func.apply("hello");//如果func.apply返回null,那么调用result的方法就会抛出空指针异常```但在这个例子中,`toUpperCase`不会返回null,所以是安全的。但如果是其他方法,比如:```javaFunction<String,String>func=s->null;Stringresult=func.apply("hello");System.out.println(result.length());//这里会抛出NullPointerException```所以,问题可能不是发生在`accept`方法上,而是发生在后续使用返回值的时候。鉴于上述分析,我们提供以下解决方案:###解决方案1.**检查方法引用或Lambda表达式**:确保它们不会返回null,或者在返回null的情况下,调用者能够正确处理。2.**使用`Optional`**:在可能返回null的方法调用处,使用`Optional`包装返回值,避免空指针异常。```javaOptional.ofNullable(someMethodThatMightReturnNull()).ifPresent(value->{//使用value,这里不会出现空指针,因为只有非空时才会执行});```3.**在反射调用中检查返回值**:如果使用反射调用方法,检查返回值是否为null,并做相应处理。```javaMethodmethod=...;Objectresult=method.invoke(obj,args);if(result==null){//处理null情况}else{//处理非空情况}```4.**修改自定义函数式接口**:如果问题发生在自定义的函数式接口上,考虑是否可以将返回型改为`Optional`,或者确保实现不返回null。###相关问题根据用户的问题,生成一些相关问题,帮助用户深入理解:§§相关问题§§1.Java中`Consumer`接口的`accept`方法可以返回值吗?2.如何在Java中避免空指针异常?3.Java方法引用有哪几种形式?使用时需要注意什么?4.使用反射调用方法时,如何处理可能返回null的情况?5.`Optional`Java中如何帮助避免空指针异常?###引用说明在回答中,我们参考了用户提供的引用[1]中关于方法引用的内容,但具体问题还需要具体分析。用户的问题可能与方法引用有关,但需要更多的上下文信息才能准确定位。我们建议用户提供相关代码片段,以便更准确地解决问题。[^1]:用户提供的引用[1]中展示了方法引用的例子,特别是构造器引用(`ArrayList::new`)。[^2]:用户提供的引用[2]是关于zkclient的依赖配置,与当前问题无关。</think>### 解决 Java 方法 `accept()` 因返回值为 null 导致的异常问题 在 Java 中,当函数式接口(如 `Consumer`)的 `accept()` 方法因返回值处理不当抛出异常时,通常由以下原因引起: 1. **方法签名不匹配**:函数式接口要求 `void` 返回值,但 Lambda 或方法引用返回了对象 2. **空指针解引用**:对 `accept()` 的返回值(应为 `void`)进行非法操作 3. **反射调用异常**:通过反射调用方法时未处理返回值 null 的情况 --- ### 解决方案 #### 1. 修正函数式接口误用(推荐方案) **问题根源**:`Consumer.accept()` 是 `void` 方法,不应返回任何值 ```java // 错误示例:Lambda 尝试返回 String Consumer<String> consumer = s -> { return s.toUpperCase(); // ❌ 编译错误:Consumer 不能返回值 }; // 正确写法:无返回值的 Lambda Consumer<String> validConsumer = s -> { System.out.println(s.toUpperCase()); // ✅ 无返回值 }; ``` #### 2. 处理反射调用的返回值 当通过反射调用方法时,需显式处理 `null` 返回值: ```java Method method = obj.getClass().getMethod("methodName"); Object result = method.invoke(obj); // 可能返回 null // 安全处理返回值 if (result != null) { // 处理非空结果 } else { // 处理 null 情况 System.out.println("方法返回值为 null"); } ``` #### 3. 使用 `Optional` 避免空指针 对于可能返回 `null` 的方法调用: ```java Optional.ofNullable(getNullableValue()) .ifPresent(value -> { // 安全处理非空值 System.out.println("值存在: " + value); }); ``` --- ### 关键注意事项 1. **函数式接口规则**: - `Consumer.accept()`:必须为 `void`,无返回值 - `Function.apply()`:允许返回值,需处理 `null` ```java Function<String, String> func = s -> s != null ? s.toUpperCase() : null; // ✅ 合法 ``` 2. **反射最佳实践**: ```java try { Method method = ...; Object result = method.invoke(target); if (result == null && method.getReturnType() != void.class) { throw new IllegalStateException("非 void 方法返回了 null"); } } catch (IllegalAccessException | InvocationTargetException e) { // 处理反射异常 } ``` 3. **空安全设计**: - 使用 `@Nullable` 注解标注可能返回 `null` 的方法 - 用 `Objects.requireNonNull()` 验证参数: ```java public void acceptValue(String input) { Objects.requireNonNull(input, "输入不能为 null"); // 安全使用 input... } ``` --- ### 错误示例分析 ```java Consumer<String> consumer = s -> s.substring(0,1); // ❌ // 编译器报错:Lambda 表达式返回 String,但 Consumer 需要 void ``` **修正方案**: ```java // 方案1:改用 Function Function<String, String> func = s -> s.substring(0,1); // 方案2:在 Consumer 内部消耗结果 Consumer<String> consumer = s -> { String result = s.substring(0,1); System.out.println(result); }; ``` [^1]: Java 方法引用规范要求严格匹配函数式接口签名 [^2]: 反射 API 需显式处理返回值 null 情况 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值