可以做些什么来避免在使用 Records 时出现由于自动装箱而导致的隐藏错误

Raj*_*jat 1 java autoboxing java-8

有时我会编写一些小脚本,用于管理数据库中的记录或生成一些用于报告目的的数据。

大多数时候我们使用Long类型作为用户实体的 ID。如果我执行以下操作:

List<Long> listOfLong = Arrays.asList(1L, 2L, 3L);
System.out.println(listOfLong.contains(2));
Run Code Online (Sandbox Code Playgroud)

它返回,false但为此:

System.out.println(integers.contains(2L));
Run Code Online (Sandbox Code Playgroud)

它返回true

我们不应该得到这样的编译时错误吗?

Ste*_*n C 5

您没有编译错误的原因是containsin的签名Collection<E>定义为:

boolean contains(Object o)
Run Code Online (Sandbox Code Playgroud)

没错,Object。不是contains(<E> o)

(为什么他们以这种方式定义它?我知道这是为了与 Java 5 之前的 Java 版本兼容,因为集合类型不是通用的。如果他们contains在 Java 5 中重新定义了该方法以只允许<E>参数,它会破坏许多在 Java 早期版本中工作的代码。)

所以,就因为编译器而言,一个Integer实例调用时,适当的参数类型containsList<Long>

我们不应该得到这样的编译时错误吗?

不,它是有效的 Java。

(如果你的意思是“应该”的意思是“如果”的话会更好……那么我同意。但是contains这样定义是有原因的,而且没有回头路。)

可以做些什么来避免隐藏的错误

尝试使用静态代码分析器,如 FindBugs 或 PMD。我不确定这些工具是否会检测到这个特定的错误,但他们可能会发现其他错误。

除此之外:

  • 更多的测试。
  • 更改您的代码库以使用自定义类型的 id。一种不能自动装箱/拆箱的。(很多工作,治愈可能比疾病更糟糕......正如他们所说。)