我有以下DTO:
@Data
@RequiredArgsConstructor
public class MenuItemExpandedDTO {
private UUID uuid;
private List<ModifierGroupDTO> modifierGroupDtoList;
private List<AllergenInfo> allergenInfoList;
public MenuItemExpandedDTO(
PropertiesDTO propertiesDto,
List<ModifierGroupDTO> modifierGroupDtoList,
List<AllergenInfo> allergenInfoList
) {
this.uuid = propertiesDto.getUuid();
this.modifierGroupDtoList = modifierGroupDtoList;
this.allergenInfoList = allergenInfoList;
}
}
在SonarQube分析中,我得到了一个由allergenInfoList
引起的漏洞,如所述
消息:存储allergeninfolist的副本
所以,我不确定问题是什么,但在修复此错误之前,我想知道该代码有什么问题?在某些页面中,建议初始化列表,例如private List<AllergenInfo> allergenInfoList = Collections.emptyList()
。但这不是我在我的项目中遵循的方式。那么,这段代码的问题是什么呢?
SonarQube告诉你在构造函数中接收List
时要小心。为什么?因为调用者持有对该List
的引用,并且如果它不是不可变的,它可以对它执行以下操作:
- 通过添加或删除元素来改变
List
的内容,实际影响MenuItemExpandedDTO
。 - 更改
List
中包含的对象,如果它们不是不可变的。这意味着List
中的AllergenInfo
对象可以被更改,从而影响MenuItemExpandedDTO
对象。
To tackle 1。,您可以按照SonarQube的建议简单地存储List
的副本:
public MenuItemExpandedDTO(
PropertiesDTO propertiesDto,
List<ModifierGroupDTO> modifierGroupDtoList,
List<AllergenInfo> allergenInfoList
) {
this.uuid = propertiesDto.getUuid();
this.modifierGroupDtoList = new ArrayList<>(modifierGroupDtoList);
this.allergenInfoList = new ArrayList<>(allergenInfoList);
}
}
处理2。更棘手、更简单、更可靠的解决方案是使用不可变对象。您可以在https://www.baeldung.com/java-immutable-object上阅读更多关于这方面的内容,以及如何设计您的类以获得不可变对象。
public class MenuItemExpandedDTO {
private final UUID uuid;
private final List<ModifierGroupDTO> modifierGroupDtoList;
private final List<AllergenInfo> allergenInfoList;
public MenuItemExpandedDTO(PropertiesDTO propertiesDto,
List<ModifierGroupDTO> modifierGroupDtoList,
List<AllergenInfo> allergenInfoList) {
this.uuid = propertiesDto.getUuid();
this.modifierGroupDtoList = new ArrayList<>(modifierGroupDtoList);
this.allergenInfoList = new ArrayList<>(allergenInfoList);
}
public UUID getUuid() {
return UUID;
}
public List<ModifierGroupDTO> getModifierGroupDtoList() {
return new ArrayList<>(modifierGroupDtoList);
}
public List<AllergenInfo> getAllergenInfoList() {
return new ArrayList<>(allergenInfoList);
}
}
请记住,ModifierGroupDTO
和AllergenInfo
也必须是不可变的,这样MenuItemExpandedDTO
是100%不可变的。