10

我在我的项目中运行了 FindBugs,并收到以下警告:

new foo.pkg.Key(Client, Product, Date, String)可以通过将外部可变对象存储到Key.expireDateMALICIOUS_CODE EI_EXPOSE_REP2中来公开内部表示 60 Medium

Key是一个实体,它有一个Date expireDate, 具有各自的 getter 和 setter,并在构造函数中使用它们。

实际上,我只是返回 a (Date) dataNascimento.clone(),并在 setter 中使用相同的策略。

问题(按向后逻辑顺序):

  • 这是更好的方法吗?
  • 之前的代码有什么问题?
  • 为什么这样做是错误的?
  • 是因为 Date 是可变类型吗?
4

2 回答 2

10

我建议(Date) dataNascimento.clone()在构造函数中执行您的调用(直接或通过您的设置器)。

是的,FindBugs 会警告您,因为数据是可变的。您可能在 setter 和 getter 中有克隆调用,但您仍然会收到警告,因为您仍然可以更改构造函数中的日期。

于 2012-10-15T16:10:40.150 回答
1

将参数类型更改为不可变的类型LocalDate(Java 8)。

好处:之后没有人可以修改这个(不可变的)日期。

错误描述

请参阅 Spotbugs 的文档 >错误描述: EI2 EI_EXPOSE_REP2可能通过合并对可变对象的引用来公开内部表示

此代码将对外部可变对象的引用存储到对象的内部表示中。如果实例由不受信任的代码访问,并且对可变对象的未经检查的更改会危及安全性或其他重要属性,则您将需要做一些不同的事情。在许多情况下,存储对象的副本是更好的方法。

注意:您也可以在FindBugs 的错误描述中查找这样的描述。

修复:使用不可变的日期对象,例如LocalDate

要修复 in 等不可变参数的 FindBugs 问题new foo.pkg.Key(Client, Product, Date, String),请将构造函数更改为接受不可变的日期对象,例如:

  • 乔达时间DateTime

    所有主要的日期时间类都是不可变的(如字符串),并且在创建后无法更改。

  • 自 Java 8或 Java 8 Date & Time API (JSR 310)LocalDate的其他不可变版本以来。请参阅 Ben Evans 和 Richard Warburton (2014) 的文章中的新 Time API 概念:Java SE 8 Date and Time

    不可变值类。Java 中现有格式化程序的严重弱点之一是它们不是线程安全的。这给开发人员增加了以线程安全的方式使用它们的负担,并在他们的日期处理代码的日常开发中考虑并发问题。新 API 通过确保其所有核心类都是不可变的并表示明确定义的值来避免这个问题。

var today = LocalDate.now();
var key = new Key(client, product, today, "immutable date - can't change")`

// no modification possible:
today.setYear(1988); // no such modifier exists

此外,您的实体类中的构造函数和字段需要针对不变性进行设计,例如:

package foo.pkg;

public class Key {
    private LocalDate expiryDate; // now immutable (before: Date)

    // remaining fields omitted

    public Key(Client client, Product product, LocalDate expiryDate, String s) {
       this.expiryDate = expiryDate;
       
      // remaining initialization omitted
    }

}

查看相关问题

于 2021-09-29T08:51:21.580 回答