【问题标题】:The equals() method in Java works unexpectedly on Long data typeJava 中的 equals() 方法在 Long 数据类型上意外工作
【发布时间】:2011-12-29 17:53:48
【问题描述】:

让我们首先考虑 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.");
}

这些语句与前面的 sn-p 中提到的语句等效,只是数据类型已更改并且它们的行为完全相反。

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

【问题讨论】:

  • 文档说 .equals 只有当两个对象都是 long 类型时才返回 true。
  • 我试过 if(temp1.longValue()==1)if(temp1.equals(1l) 都按预期工作。

标签: java


【解决方案1】:

您将Longint 进行比较。 java.lang.Long#equals 的 javadoc 说 equals 方法

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

改为尝试System.out.println(new Long(1).equals(1L)); 现在您将LongLong 进行比较,而不是将LongInteger 进行比较,它将打印true

【讨论】:

  • @TheLQ 你问能不能做new Long(1L)?是的你可以。 1L 基本上代表一个long 类型。由于Long 构造函数接受longs,它将接受1L 作为构造函数参数。
  • @JackEdmonds 这里不需要new Long(...)1L 就足够了
  • @Eugene 1L 是一个未装箱的原语,你不能这样做 1L.equals(1L)。你肯定需要一个Long 对象才能使用它的equals() 方法。
  • 啊,所以您建议将单个语句重写为两个。当然,是的,这是可以做到的。但是“没必要”。
【解决方案2】:

您可以进行这种比较的原因是因为 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 对象中。

【讨论】:

    【解决方案3】:

    文字值1 不是long,而是int。试试上面的代码:

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

    if (temp1.equals(1L))
    

    如您所见,在文字值1 之后放置一个L 表示它是一个long,然后比较会按预期进行。

    【讨论】:

      【解决方案4】:

      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(和 not equals)。虽然如果你知道你只会得到 long 和 ints,那么生活会更简单,因为你可以执行以下操作。

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

      【讨论】:

      • 如果你能添加一个例子和官方来源的提到的“完全可靠的方法”来比较两个未知类型的数字的值,那就太好了。无论如何,谢谢并投票!
      • 谁能解释更多关于“但是,当您使用盒装版本时,类型可以在编译时知道,但在执行比较时不知道。”?由于多态性,我怀疑这会以另一种方式出现。如果你能帮助我,非常感谢!
      【解决方案5】:

      根据Javadoc's page on Long.equals method 仅在以下情况下计算为 true

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

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

      【讨论】:

        【解决方案6】:

        这种行为与将1 转换为Integer 的自动装箱一致,然后将其与另一个Integer(1) 进行比较。将LongInteger 进行比较得到false

        如果您使用1LLong 进行比较,则结果为true

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

              【解决方案9】:

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

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

              因此,如果您要使用 Integer Value int 代替 Long 值,则第一次检查将失败,因此您将得到 false 作为结果。

              【讨论】:

                【解决方案10】:

                您可以在不使用 equals() 的情况下比较 Long/integer 值。据我所知,只有在比较字符串时才需要这样做。

                【讨论】:

                  猜你喜欢
                  • 2014-04-24
                  • 1970-01-01
                  • 2010-09-16
                  • 2019-05-13
                  • 2016-09-28
                  • 2018-03-29
                  • 1970-01-01
                  相关资源
                  最近更新 更多