SonarQube:"Store a copy of "productAllergenInfos“”

SonarQube: "Store a copy of "productAllergenInfos""

我有以下 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 告诉您在构造函数中接收 Lists 时要小心。为什么?因为调用者持有对该 List 的引用,如果它不是不可变的,它可以对其执行以下操作:

  1. 通过向其中添加或删除元素来更改 List 内容,实际上会影响您的 MenuItemExpandedDTO
  2. 更改 List 中包含的对象(如果它们不是不可变的)。这意味着可以更改 List 中的 AllergenInfo 个对象,影响您的 MenuItemExpandedDTO 个对象。

要解决 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);
    }
}

请记住,ModifierGroupDTOAllergenInfo 也必须是不可变的,因此 MenuItemExpandedDTO 是 100% 不可变的。