PMD引用接口的可变对象

时间:2019-02-14 15:32:44

标签: java pmd

类似于this question。我有一个界面DateRangeModel

我使用它来自动验证实施者中的日期:

public interface DateRangeModel {

    @ApiModelProperty(value = "From date. Must be less than to date.")
    @Column()
    Date getFromDate();

    void setFromDate(Date date);

    @ApiModelProperty(value = "To date. Must be greater than to date.")
    @Column()
    Date getToDate();

    void setToDate(Date date);


    /**
     * Checks that if both dates are populated, a valid date range is used.
     *
     * @return true if the date is a valid range.
     */
    @AssertTrue(message = "To date must be greater than or equal to from date.")
    @JsonIgnore
    default boolean areDatesValid() {

        if (getToDate() != null && getFromDate() != null) {
            return !getFromDate().after(getToDate());
        }
        return true;
    }
}

我是这样实现的:

@EqualsAndHashCode
@Data
@Builder
public class BirthdayParty implements DateRangeModel {

    Date fromDate;
    Date toDate;
    String name;

}

哪个可以编译并且似乎可以工作,但是运行PMD时出现该错误:

Returning a reference to a mutable object value stored in one of the object's fields exposes the internal representation of the object.

我该如何完成我想要的(与日期/日期验证的接口)而不必在所有实现者中实现setDate方法(我认为这样做会达到目的)?

1 个答案:

答案 0 :(得分:2)

问题在于java.util.Date是可变的,并且您在getter中将其返回。所以有人可以这样做:

BirthdayParty party = ...;
Date fromDate = party.getFromDate();
...
Date someDate = fromDate;
...
// you might not be aware that this also changes the fromDate in party
someDate.setTime(12345678);

您可以做四件事:

  1. 禁用PMD规则。
  2. 在所有使用这些a类之一的地方都禁止显示警告。
  3. 不要使用Lombok并将日期复制到您的setter和getter中,而不仅仅是将引用存储/返回日期。
  4. 使用java.time.ZonedDateTime(或LocalDateTime)代替日期。 ZonedDateTime是不可变的,不应导致此警告。

我建议第四个选择。不仅因为它摆脱了PMD警告,而且还因为Java 8中的新时间API比java.util.Date更好,更易于使用。