【问题标题】:How to solve EI_EXPOSE_REP2 and why exactly its wrong如何解决 EI_EXPOSE_REP2 以及为什么它错了
【发布时间】:2012-05-20 01:02:22
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: java date findbugs


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

      错误说明

      查看 Spotbugs 的文档 > 错误描述 for EI_EXPOSE_REP2: EI2: May expose internal representation by incorporating reference to mutable object:

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

      注意:您也可以在FindBugs' bug descriptions 中查找此类描述。

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

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

      • Joda Time 的DateTime:

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

      • 自 Java 8 LocalDate 或 Java 8 的其他不可变项日期和时间 API (JSR 310)。请参阅 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
          }
      
      }
      

      查看相关问题

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-22
        • 1970-01-01
        相关资源
        最近更新 更多