导致 nullpointer 异常的 Java 可变对象

Java mutable object to causing nullpointer exception

提问人:Jack 提问时间:10/5/2021 更新时间:10/5/2021 访问量:139

问:

我有以下 DTO,我将对象传递给 s 以防止对象被更改并修复 SonarQube 错误为“消息:存储 allergenInfoList 的副本”等。ArrayList

public MenuItemDTO(
        PropertiesDTO propertiesDto,
        List<ModifierDTO> modifierDtoList,
        List<AllergenInfo> allergenInfoList
) {
    this.uuid = propertiesDto.getUuid();
    this.modifierDtoList = new ArrayList<>(modifierDtoList);
    this.allergenInfoList = new ArrayList<>(allergenInfoList);
  }
}

但是,这种方法需要 null 检查,它使我的代码变得丑陋,如下所示:

public MenuItemDTO(
        PropertiesDTO propertiesDto,
        List<ModifierDTO> modifierDtoList,
        List<AllergenInfo> allergenInfoList
) {
    this.uuid = propertiesDto.getUuid();
    if (modifierDtoList != null) {
        this.modifierDtoList = new ArrayList<>(modifierDtoList);
    }
    if (allergenInfoList != null) {
        this.allergenInfoList = new ArrayList<>(allergenInfoList);
    }
}

那么,有没有更好的方法可以在没有空检查的情况下解决问题?

爪哇岛 春天 声纳库 声纳库扫描 可变

评论

0赞 bradley101 10/5/2021
在调用构造函数之前,可以检查它们是否不为 null。但这没关系。它不必总是美丽的。

答:

1赞 pleft 10/5/2021 #1

这是一个解决方案,它处理将 null 列表作为输入参数的可能性,但它需要比简单的 null 检查更多的代码

创建一个方法,如下所示:

private <T> List<T> copyList(List<T> list) {
    return Optional.ofNullable(list)
            .map(List::stream)
            .orElseGet(Stream::empty)
            .collect(Collectors.toList());
}

或者只是使用类似的方法,并在此方法中仅执行一次 if null 检查:

private <T> List<T> copyList(List<T> list) {
    if (list != null) {
        return new ArrayList<>(list);
    }
    return new ArrayList<>();
}

并在构造函数上使用此方法,这样它看起来更优雅:

public MenuItemDTO(
        PropertiesDTO propertiesDto,
        List<ModifierDTO> modifierDtoList,
        List<AllergenInfo> allergenInfoList
) {
    this.uuid = propertiesDto.getUuid();
    this.modifierDtoList = copyList(modifierDtoList);
    this.allergenInfoList = copyList(allergenInfoList);
   
}

评论

1赞 rkosegi 10/5/2021
为什么使用 RAW ?它可以很容易地生成List
1赞 akortex 10/5/2021 #2

一个更时尚的解决方案,可以避免创建流和收集元素的需要:

例如,检查一下:

private <T> List<T> copyList(List<T> list) {
    return Optional.ofNullable(list)
        .map(ArrayList::new)
        .orElseGet(ArrayList::new);
}

这有效地检查传入的列表是否不在,继续并复制它。否则,它只会创建一个新的空列表。最重要的是,它还负责泛型和类型。null

1赞 Nowhere Man 10/5/2021 #3

最好实现一个实用程序/帮助程序方法来处理空检查(直接、使用 或 )并返回预期结果:Objects::isNullOptional

public class Util {
    public static List<?> copyOrNull(List<?> src) {
        return null == src ? src : new ArrayList<>(src);
    }

    public static List<?> copyOrEmpty(List<?> src) {
        return null == src ? Collections.emptyList() : new ArrayList<>(src);
    }
}

然后根据需要更新 DTO 代码:


public MenuItemDTO(
        PropertiesDTO propertiesDto,
        List<ModifierDTO> modifierDtoList,
        List<AllergenInfo> allergenInfoList
) {
    this.uuid = propertiesDto.getUuid();
    this.modifierDtoList = Util.copyOrNull(modifierDtoList);
    this.allergenInfoList = Util.copyOrEmpty(allergenInfoList);
}