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

时间:2011-12-29 17:53:49

标签: java

让我们首先考虑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块中的唯一语句不会执行,与前面的语句相反。怎么样?

10 个答案:

答案 0 :(得分:36)

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

  

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

而是尝试System.out.println(new Long(1).equals(1L));现在,您要将LongLong而不是LongInteger进行比较,它会打印{{ 1}}。

答案 1 :(得分:6)

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

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

if (temp1.equals(1L))

正如您所看到的,在文字值L之后加1表示它是long,然后比较按预期工作。

答案 2 :(得分:6)

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

您调用的实际方法是:

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

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

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

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

这就是它失败的原因。

这就是为什么你打电话

new Long(1).equals(1L) 

这样可行,因为Java会将1L(原始long,而不是int)自动装入Long对象,而不是Integer对象。

答案 3 :(得分:3)

根据Javadoc's page on Long.equals method仅在true评估为<{p}}

  1. 参数是Long对象
  2. 如果(1)为真,则Long个对象必须具有相等的值
  3. 在您的方案中,1int,而不是Long对象,因此失败(1),因此评估为false。如果您需要测试long,请改用1L

答案 4 :(得分:3)

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(和等于)。虽然如果你知道你只是渴望获得多头和生命,那么生活就会更简单,因为你可以做到以下几点。

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

答案 5 :(得分:2)

这种行为与自动装箱一致,将1转换为Integer,然后将Integer(1)与另一个Long进行比较。将Integerfalse进行比较会产生1L

如果您使用Longtrue进行比较,则会产生{{1}}。

答案 6 :(得分:2)

  

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}来更正} ,,,例如1,通过这样做,我们将temp1.equals(1L)对象与Long进行比较,并将结果设为TRUE

答案 7 :(得分:1)

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

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

答案 8 :(得分:1)

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,那么第一次检查将失败,因此您将得到错误的结果。

答案 9 :(得分:0)

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