Java Wrapper的比较

时间:2018-05-08 03:04:12

标签: java wrapper equality primitive-types inequality

public static void main(String[] args) {    
    System.out.println((Integer.valueOf("5000") <= Integer.valueOf("5000")));
    System.out.println((Integer.valueOf("5000") == Integer.valueOf("5000")));       
}

以上代码分别打印truefalse。这是可以理解的,但是当我们使用false时,为什么会打印==

但是,当使用<=(小于或等于)时,为什么答案为true

4 个答案:

答案 0 :(得分:2)

两个对象之间的等于运算符==意味着引用相等;它们必须引用相同的Object,因为它们的内存地址是相同的。 这也适用于所有包装。

两个对象的值可以“相等”,例如使其所有字段相等,但占用不同的内存地址。 Integer是原语int的包装器Object。

由于Integer(和所有Wrapper对象)是一个Object,a == b a, b是整数(不是整数),如果a, b引用相同的Integer对象,则返回true。

在第二个System.out.println中,您创建了两个新的Integer对象(Integer.valueOf("5000")(Integer.valueOf("5000"),它们都包含相同的包装int值。但是这些整数占用两个不同的内存地址,所以这两个不能是引用相等的。因此,因为它们不是引用相等的,==的计算结果为False。

另一方面,通常在对象中未定义less-or-equals运算符<=Integer.valueOf("5000") <= Integer.valueOf("5000"),涉及“取消整理”整数,然后比较其int值的值,如果第一个Integer的字段(int类型)的值等于第二个Integer字段的值,则返回true。在比较不等式时,Java会在Integer类上执行拆箱。

答案 1 :(得分:2)

使用<=比较包装类时,>= Java执行拆箱并比较彼此之间的实际int(或double,long等)值。因此Integer.valueOf("5000") <= Integer.valueOf("5000")将像Integer.valueOf("5000").intValue() <= Integer.valueOf("5000").intValue()一样工作,相当于5000 <= 5000

答案 2 :(得分:2)

要解释代码打印此类输出的原因,我们可能需要查看较低级别:

我将你的代码反编译为字节码级别。

第一行:

System.out.println((Integer.valueOf("5000") <= Integer.valueOf("5000")));

字节码是(无用信息被删除):

LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;  
INVOKEVIRTUAL java/lang/Integer.intValue ()I
LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;
INVOKEVIRTUAL java/lang/Integer.intValue ()I
IF_ICMPGT L1

您可以看到<=左侧部分,JVM使用Integer.valueOf函数将字符串转换为Integer对象。然后使用Integer.intValue函数提取此对象的内部值(同样称为auto-unboxing )。因此,对于左侧部分,我们得到int值。

<=的右侧部分与左侧部分相同。

最后一行IF_ICMPGT是比较这两个int值。因此,结论是如果您使用<=,Java编译器将为您执行自动取消装箱并比较内部int值。

第二行:

System.out.println((Integer.valueOf("5000") == Integer.valueOf("5000")));

字节码是(无用信息被删除):

LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;
LDC "5000"
INVOKESTATIC java/lang/Integer.valueOf (Ljava/lang/String;)Ljava/lang/Integer;
IF_ACMPNE L4

您可以看到字节码与第1行不同。它只是将字符串转换为Integer对象,但不是自动取消装箱它们。因为它们是两个单独的对象,所以它们必须具有不同的地址(在内存中)。

最后一行IF_ACMPNE将比较这两个Integer对象的地址。因此,结论是如果您使用==,Java编译器将不会自动取消装箱并比较对象地址。

还有什么

Integer缓存整数对象的范围为-128~127。这意味着如果传递一个在此范围内的字符串,您将获得完全相同的Integer对象。下面的代码将打印为true:

System.out.println((Integer.valueOf("127") == Integer.valueOf("127"))); // true

答案 3 :(得分:0)

如果您查看Integer.valueOf(String s)的的Java文档,这个问题很容易回答

  

public static Integer valueOf(String s)                         抛出NumberFormatException

     

返回 整数对象 ,其中包含指定String的值。该参数被解释为表示带符号的十进制整数,就像该参数被赋予parseInt(java.lang.String)方法一样。结果是一个Integer对象,表示字符串指定的整数值。   换句话说,此方法 返回一个等于以下值的Integer对象

   new Integer(Integer.parseInt(s))

由于Integer.valueOf("5000")返回一个Integer对象而不是一个原始int,而你正在使用==比较对象,如果两个Integer对象都没有指向,则会得到false同样的参考。

  • ==通过比较对象的身份来检查相等性。

  • .equals()通过比较对象的内容来检查相等性。

当您将对象与<><=>=进行比较时,它会给您不准确的结果,因为您没有,并且您无法执行Java中的运算符重载(即为运算符定义自定义行为并告诉它们如何比较对象)。

如果要比较对象,请在类上实现Comparable。如果要比较Integer对象,请在使用int><>=进行比较之前获取原始<=值:

Integer.valueOf("5000").intValue() <= Integer.valueOf("5000").intValue();  //true