【问题标题】:(Date) may expose internal representation by storing an externally mutable object into CategoryModel.createdDate(Date) 可以通过将外部可变对象存储到 CategoryModel.createdDate 来公开内部表示
【发布时间】:2018-01-01 05:56:22
【问题描述】:

在处理模型类时,我面临以下警告:--

com.model.products.CategoryModel.setCreatedDate(Date) may expose internal representation by storing an externally mutable object into CategoryModel.createdDate

我的模型类

@JsonInclude(Include.NON_NULL)
public class CategoryModel {

     private Date createdDate;

     public Date getCreatedDate() {

        return createdDate;

//Warning Message:--com.model.products.CategoryModel.getCreatedDate(Date) may expose internal representation by storing an externally mutable object into CategoryModel.createdDate

    public void setCreatedDate(Date createdDate) {

        this.createdDate = createdDate;

//Warning Message:--com.model.products.CategoryModel.setCreatedDate(Date) may expose internal representation by storing an externally mutable object into CategoryModel.createdDate

}

警告说明:--

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

在上面的模型类中我收到一个警告,处理这个问题的更好方法是什么?提前谢谢...

【问题讨论】:

  • 你能用LocalDate/LocalDateTime吗?
  • 虽然已折旧,但 Date 仍然可以在外部更改(突变),这可能会对您的模型产生无法预料的后果,而 LocalDate/LocalDateTime 类不能(他们返回一个新对象)
  • @MadProgrammer 所以你的意思是说我使用 LocalDate/LocalDateTime insted of date。
  • 我没有足够的上下文来知道这是否可能,但这将提供日期/时间的不可变表示
  • @MadProgrammer 好的,我试试这个非常感谢..!!!

标签: java rest date


【解决方案1】:

防守副本

您正在接受从您的类外部对可变对象的引用,以便在您的类内部使用。这意味着该可变对象的来源可以在你背后改变它的值。前一刻,您自己的对象包含今年的 6 月 3 日,然后又包含去年的 11 月 27 日。并且任何其他引用该可变对象的对象都可以在你背后以同样悲惨的方式改变它的值。

最佳做法是在收到该可变对象时制作一份防御性副本。将其内部值复制到另一个新对象中。您知道这个新对象是安全的,因为没有其他对象引用它。

如果您不了解 Java 中对象引用的这种行为,请学习一些有关 Java 编程的基础知识。可能是 Oracle.com 教程,或者 O'Reilly 出版商的关于 Java 的 Head First 书籍。

防御性副本的替代方法是首先使用不可变对象。如果不可变,则整个问题都被消除了。

java.time

您正在使用麻烦的旧日期时间类,现在已被现代 java.time 类所取代。

java.time 类是不可变的,因此如果您将每次使用 DateCalendar 替换为 java.time 类,上述问题就可以解决。在 UTC 时间线上片刻,与java.util.Date 相同,使用java.time.Instant

【讨论】:

  • 所以你的意思是说我使用私人 Instant createdDate;而不是私有日期 createdDate; ???
  • @h36p 是的。您甚至可以保留相同的方法签名,接受 Date 然后将其转换为 Instant。这种方法同时使用了我的观点,防御性副本 不可变对象。 private Instant whenCreated ;this.whenCreated = passedUtilDate.toInstant() ; 但最好尽可能避免使用这些遗留类,在整个代码库中使用 java.time。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-06
  • 1970-01-01
  • 2012-02-15
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多