Java 可变对象导致空指针异常
Java mutable object to causing nullpointer exception
我有以下 DTO,我将对象传递给 ArrayList
s 以防止对象被更改并将 SonarQube 错误修复为 “消息:存储 allergenInfoList 的副本”。 =21=],等等
public MenuItemDTO(
PropertiesDTO propertiesDto,
List<ModifierDTO> modifierDtoList,
List<AllergenInfo> allergenInfoList
) {
this.uuid = propertiesDto.getUuid();
this.modifierDtoList = new ArrayList<>(modifierDtoList);
this.allergenInfoList = new ArrayList<>(allergenInfoList);
}
}
但是,这种方法需要空值检查,它使我的代码变得丑陋,如下所示:
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);
}
}
那么,有没有更好的方法可以在不进行空检查的情况下解决问题?
这是一个处理将空列表作为输入参数的可能性的解决方案,但它需要比简单的空检查更多的代码
创建如下方法:
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);
}
一个更时尚的解决方案,可能会避免创建流和收集元素的需要:
例如检查这个:
private <T> List<T> copyList(List<T> list) {
return Optional.ofNullable(list)
.map(ArrayList::new)
.orElseGet(ArrayList::new);
}
这有效地检查了传入的列表是否为null
不是,继续并复制它。否则,它只是创建一个新的空列表。除此之外,它还负责泛型和类型。
最好实现一个 utility/helper 方法来处理空检查(直接使用 Objects::isNull
或 Optional
)和 return 预期结果:
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);
}
我有以下 DTO,我将对象传递给 ArrayList
s 以防止对象被更改并将 SonarQube 错误修复为 “消息:存储 allergenInfoList 的副本”。 =21=],等等
public MenuItemDTO(
PropertiesDTO propertiesDto,
List<ModifierDTO> modifierDtoList,
List<AllergenInfo> allergenInfoList
) {
this.uuid = propertiesDto.getUuid();
this.modifierDtoList = new ArrayList<>(modifierDtoList);
this.allergenInfoList = new ArrayList<>(allergenInfoList);
}
}
但是,这种方法需要空值检查,它使我的代码变得丑陋,如下所示:
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);
}
}
那么,有没有更好的方法可以在不进行空检查的情况下解决问题?
这是一个处理将空列表作为输入参数的可能性的解决方案,但它需要比简单的空检查更多的代码
创建如下方法:
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);
}
一个更时尚的解决方案,可能会避免创建流和收集元素的需要:
例如检查这个:
private <T> List<T> copyList(List<T> list) {
return Optional.ofNullable(list)
.map(ArrayList::new)
.orElseGet(ArrayList::new);
}
这有效地检查了传入的列表是否为null
不是,继续并复制它。否则,它只是创建一个新的空列表。除此之外,它还负责泛型和类型。
最好实现一个 utility/helper 方法来处理空检查(直接使用 Objects::isNull
或 Optional
)和 return 预期结果:
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);
}