Java 如何避免在处理记录时由于自动装箱而出现以下隐藏错误

Java 如何避免在处理记录时由于自动装箱而出现以下隐藏错误,java,java-8,autoboxing,Java,Java 8,Autoboxing,有时我会编写小脚本,以管理数据库中的记录或生成一些用于报告目的的数据 大多数情况下,我们使用Long类型作为用户实体的ID。如果我这样做: List<Long> listOfLong = Arrays.asList(1L, 2L, 3L); System.out.println(listOfLong.contains(2)); 它返回true 我们不应该得到这样的编译时错误吗?在对象类型参数上使用equals方法进行检查 列表包含至少一个元素e,使得(o==null?e==null

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

大多数情况下,我们使用
Long
类型作为用户实体的ID。如果我这样做:

List<Long> listOfLong = Arrays.asList(1L, 2L, 3L);
System.out.println(listOfLong.contains(2));
它返回
true

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

在对象类型参数上使用equals方法进行检查

列表包含至少一个元素e,使得
(o==null?e==null:o.equals(e))

如果您不记得/不确定您将在使用它之前设置值

您可以先将其强制转换为long,然后使用
long.valueOf

List<Long> listOfLong = Arrays.asList(1l, 2l, 3l);
System.out.println(listOfLong.contains(Long.valueOf(2)));
listOfLong=Arrays.asList(1l、2l、3l);
System.out.println(listOfLong.contains(Long.valueOf(2));
或者将值2作为方法参数发送,这样它在方法签名中会很长

public void myMethod(Long number) {
     List<Long> listOfLong = Arrays.asList(1l, 2l, 3l);
     System.out.println(listOfLong.contains(number));
}
public void myMethod(长编号){
listOfLong=Arrays.asList(1l、2l、3l);
System.out.println(listOfLong.contains(number));
}
使用equals方法检查对象类型参数

列表包含至少一个元素e,使得
(o==null?e==null:o.equals(e))

如果您不记得/不确定您将在使用它之前设置值

您可以先将其强制转换为long,然后使用
long.valueOf

List<Long> listOfLong = Arrays.asList(1l, 2l, 3l);
System.out.println(listOfLong.contains(Long.valueOf(2)));
listOfLong=Arrays.asList(1l、2l、3l);
System.out.println(listOfLong.contains(Long.valueOf(2));
或者将值2作为方法参数发送,这样它在方法签名中会很长

public void myMethod(Long number) {
     List<Long> listOfLong = Arrays.asList(1l, 2l, 3l);
     System.out.println(listOfLong.contains(number));
}
public void myMethod(长编号){
listOfLong=Arrays.asList(1l、2l、3l);
System.out.println(listOfLong.contains(number));
}
您问:

我们不应该为这样的事情得到一个编译时错误吗

是的,我更喜欢这样,如果Java今天又从头开始的话,也许会是这样

如果这在我的代码中是一个严重的问题,我会为这个数字创建一个包装器,例如

class UserId {
  public UserId(long id) { ... }
  public long getId() { ... }
}
你问:

我们不应该为这样的事情得到一个编译时错误吗

是的,我更喜欢这样,如果Java今天又从头开始的话,也许会是这样

如果这在我的代码中是一个严重的问题,我会为这个数字创建一个包装器,例如

class UserId {
  public UserId(long id) { ... }
  public long getId() { ... }
}

不存在编译错误的原因是
集合中
包含的签名定义为:

boolean contains(Object o)
没错,
对象
。非
包含(o)

(他们为什么这样定义它?我知道这是为了在集合类型不是泛型的情况下与Java 5之前的Java版本兼容。如果他们在Java 5中重新定义
contains
方法,只允许
参数,那么会破坏许多在Java早期版本中工作的代码。)

因此,就编译器而言,
整数
实例是调用
列表
上的
包含
时合适的参数类型

我们不应该为这样的事情得到一个编译时错误吗

不,它是有效的Java

(如果你的意思是“应该”,意思是“如果……那就更好了”,那么我同意。但是
包含
这样定义是有原因的,没有回头路了。)

如何避免隐藏的错误

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

除此之外:

  • 更多的测试
  • 将代码库更改为使用自定义ID类型。不能自动装箱/取消装箱的文件。(很多工作,治疗可能比疾病更糟……正如他们所说。)

不存在编译错误的原因是
集合中
包含的签名定义为:

boolean contains(Object o)
没错,
对象
。非
包含(o)

(他们为什么这样定义它?我知道这是为了在集合类型不是泛型的情况下与Java 5之前的Java版本兼容。如果他们在Java 5中重新定义
contains
方法,只允许
参数,那么会破坏许多在Java早期版本中工作的代码。)

因此,就编译器而言,
整数
实例是调用
列表
上的
包含
时合适的参数类型

我们不应该为这样的事情得到一个编译时错误吗

不,它是有效的Java

(如果你的意思是“应该”,意思是“如果……那就更好了”,那么我同意。但是
包含
这样定义是有原因的,没有回头路了。)

如何避免隐藏的错误

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

除此之外:

  • 更多的测试
  • 将代码库更改为使用自定义ID类型。不能自动装箱/取消装箱的文件。(很多工作,治疗可能比疾病更糟……正如他们所说。)

添加到另一个正确答案:虽然这不是编译错误(因为没有违反JLS中的任何内容),但您的工具可能会发出警告。Eclipse将告诉您:

集合上的
包含(对象)
的不太可能的参数类型
int

集合上的
包含(对象)
的不太可能的参数类型
long


添加到另一个正确答案中:虽然这不是编译错误(因为JLS中没有违反任何内容),但您的工具可能会发出警告。Eclipse将告诉您:

集合上的
包含(对象)
的不太可能的参数类型
int

不太可能的参数类型<代码