我有一个带有私有构造函数的最终课程:
public final class Constants {
public static final Date DEFAULT_DATE;
static {
// some code that creates localDate
DEFAULT_DATE = localDate.toDate();
}
private Constants() {
}
}
sonarlint发出警告:
Make DEFAULT_DATE protected
reason: Mutable fields should not be "public static"
将其声明为受保护是没有意义的。该类被声明为final-因此无法继承。其次,我在其他类中使用DEFAULT_DATE,因此它必须是公共的。
此外,构造函数被声明为私有,因此无法创建任何对象。
为什么sonarlint强迫保护DEFAULT_DATE?
答案 0 :(得分:1)
这是因为Date类是可变的,因此如果任何对象都引用了您的Constants对象,它们可以在不知情的情况下更改日期值。最好将其设置为私有并提供一个返回值副本的getter。
答案 1 :(得分:1)
我已经在评论中提到了。我重申这些要点,并在下面全面添加一些新要点。
final
关键字可以防止重新分配,即,您不能再次使用=
分配运算符。但是final
关键字不能阻止点运算符.
。使用点运算符可以修改日期对象的状态。
Constants.DEFAULT_DATE.setTime(204587433443L)
将修改您假定的固定日期。您正在执行静态分析工具意味着您拥有代码。即使它是旧代码,也可以对其进行重构。如果它不是您控制的部分,则可以请求处理代码的团队对其进行重构。如果它属于某个第三方图书馆,则可能您可以向他们发送邮件并等待他们的回复,并且如果图书馆所有者不打算更正此错误,则可能是您应该使用另一个图书馆,因为当前图书馆可能拥有一些类似的其他问题。
答案 2 :(得分:0)
回答我自己的问题:
正如其他解释的java.util.Date
是可变的,因此将其提供为常量(实际上不是常量)是一个糟糕的设计。
@ nits.kk提供了一个更好的解决方案,“将Date的长值保留为常量”,并使用让调用者将长值转换为Date对象。
public static final long DEFAULT_DATE = <long value representing the required date>;
对此和我现在在代码中如何使用的一种改进是使用java.time.Instant
,它是一个不变的对象
public static final Instant DEFAULT_DATE = Instant.parse("<ISO-formatted-date>");
这样,我保留了预期的Date对象,并且静态检查器将不再发出警告/错误。