public static void main(String[] args) {
System.out.println((Integer.valueOf("5000") <= Integer.valueOf("5000")));
System.out.println((Integer.valueOf("5000") == Integer.valueOf("5000")));
}
以上代码分别打印true
和false
。这是可以理解的,但是当我们使用false
时,为什么会打印==
。
但是,当使用<=
(小于或等于)时,为什么答案为true
?
答案 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)
的
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