Java中的equals()方法在Long数据类型上意外地工作

我们首先考虑Java中的以下表达式。

Integer temp = new Integer(1); System.out.println(temp.equals(1)); if(temp.equals(1)) { System.out.println("The if block executed."); } 

这些所有陈述都很好。 毫无疑问。 表达式temp.equals(1)按预期计算为true ,因此if块中的唯一语句将被执行。


现在,当我将数据类型从Integer更改为Long ,语句temp1.equals(1)意外地评估为false ,如下所示。

 Long temp1 = new Long(1); System.out.println(temp1.equals(1)); if(temp1.equals(1)) { System.out.println("The if block executed."); } 

这些是前面片段中提到的等价语句,只是数据类型已经改变,它们的行为正好相反。

表达式temp1.equals(1)被计算为false ,因此, if块中的唯一语句不会执行与前面语句相反的语句。 怎么样?

你将Longint进行比较。 java.lang.Long#equals的javadoc表示equals方法

将此对象与指定的对象进行比较。 当且仅当参数不为null并且是包含与此对象相同的long值的Long对象时,结果才为真。

而是尝试System.out.println(new Long(1).equals(1L)); 现在你要比较Long to a Long而不是Long to Integer ,它将打印为true

字面值1 long ,它是一个int 。 请尝试使用以上代码:

 System.out.println(temp1.equals(1L)); 

 if (temp1.equals(1L)) 

如您所见,在字面值1之后放置一个L表示它很long ,然后比较按预期工作。

您可以进行比较的原因是因为Java中的自动装箱。

您调用的实际方法是:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Long.html#equals(java.lang.Object

这是将您的Long对象与其他对象进行比较,而不是与实际的原始int进行比较。

调用该方法时会发生的情况是您的原始integer(1)被自动装箱到一个Object(Integer)因此您实际上正在调用:

 new Long(1).equals(new Integer(1)); 

这就是它失败的原因。

这就是你打电话的原因

 new Long(1).equals(1L) 

这样可以工作,因为Java会将1L (原始long ,而不是int )自动装箱到Long对象中,而不是Integer对象。

根据Javadoc在Long上的页面 , .equals方法只有在得到时.equals计算为true

  1. 参数是一个Long对象
  2. 如果(1)为真,则Long对象必须具有相等的值

在您的方案中, 1int ,而不是Long对象,因此它失败(1),因此计算结果为false。 如果您需要long测试,请改用1L

Java很懒惰。

当您执行以下比较时,java会自动将int转换为long(因为long可以包含int可以包含的任何值)。 比较是在两个多头而不是两个整数之间。

 int i = 1; long l = 1L; boolean b = i == l; 

Java能够这样做,因为有关il的类型信息在编译时执行比较时是已知的。 但是,当您使用盒装版本时,可以在编译时知道类型,但在执行比较时则不知道 。 这是因为比较必须在equals方法中完成,并且由于equals将Object作为参数,因此类型信息会丢失。 因此,Java是懒惰的,只检查两个盒装数字是否相等,如果它们都是相同Number类的实例(例如,Integer,或者都是Long,或者两者都是Double等等)。

原来唯一完全可靠的方法是在运行时比较两个未知类型的数字,将两者都转换为字符串,然后转换为BigDecimal,然后使用方法compareTo(而不是 equals)。 虽然如果你知道你只是渴望获得多头和生命,那么生活就会变得更简单,因为你可以做到以下几点。

 Number n0 = new Long(1L); Number n1 = new Integer(1); boolean equal = n0.longValue() == n1.longValue(); 

该行为与自动装箱一致,将1转换为Integer ,然后将其与另一个Integer(1)进行比较。 将Long转换为Integer产生false

如果你使用1L来比较Long那么它将产生true

Long temp1 = new Long(1); 的System.out.println(temp1.equals(1));

if(temp1.equals(1)){System.out.println(“if块执行。”); }

在这段代码中, temp1.equals(1)Long对象与Integer对象进行比较,得到结果为false,我们可以通过使用1L而不是1来纠正它,例如temp1.equals(1L) ,通过这样做,我们进行比较Long对象,结果为TRUE

类Long的equals()方法的实现说明了原因:

 public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false; } 

Java.lang.Long中的equals方法最初仅在比较值之后才以instanceOf Long检查开始。

 public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false; } 

因此,如果您要在Long值的位置使用Integer Value,那么第一次检查将失败,因此您将得到错误的结果。

您可以在不使用equals()的情况下比较长整数值。 只有在我比较字符串时才需要这样做。