我知道如果你把一个装箱的基本整数和一个常量比较,比如:
Integer a = 4;
if (a < 5)
``` `a` 将自动取消装箱,比较将工作。
然而,当你比较两个盒子时会发生什么 `Integers` 想要比较相等还是小于/大于?
Integer a = 4;
Integer b = 5;
if (a == b)
上面的代码会导致检查它们是否是同一个对象,或者在这种情况下会自动取消装箱吗?
关于:
Integer a = 4;
Integer b = 5;
if (a < b)
?
我知道如果你把一个装箱的基本整数和一个常量比较,比如:
Integer a = 4;
if (a < 5)
``` `a` 将自动取消装箱,比较将工作。
然而,当你比较两个盒子时会发生什么 `Integers` 想要比较相等还是小于/大于?
Integer a = 4;
Integer b = 5;
if (a == b)
上面的代码会导致检查它们是否是同一个对象,或者在这种情况下会自动取消装箱吗?
关于:
Integer a = 4;
Integer b = 5;
if (a < b)
?
10条答案
按热度按时间gmol16391#
热释光;我的意见是用一元数
+
在检查值是否相等时触发其中一个操作数的解装箱,否则只需使用数学运算符。基本原理如下:已经提到过
==
比较Integer
身份比较,这通常不是程序员想要的,目的是做价值比较;尽管如此,我还是做了一些关于如何最有效地进行比较的科学研究,包括代码紧凑性、正确性和速度。我用了通常的方法:
经过编译和反编译得到了以下代码:
很容易看出,方法1调用
Integer.equals()
(显然),方法2-4产生完全相同的代码,通过.intValue()
然后直接比较它们,方法5只会触发身份比较,这是比较值的错误方法。自(如js所述)
equals()
招致开销(必须这样做instanceof
方法2-4将以完全相同的速度工作,在紧密循环中使用时明显优于方法1,因为hotspot不太可能优化cast&instanceof
.它与其他比较运算符(例如。
<
/>
)-使用时会触发拆箱compareTo()
不会-但这一次,操作是高度优化的hs自intValue()
只是一个getter方法(要优化的主要候选方法)。在我看来,很少使用的版本4是最简洁的方法——每一个经验丰富的c/java开发人员都知道,在大多数情况下,一元加号等于cast to
int
/.intValue()
-虽然这对一些人来说可能是一个小小的wtf时刻(大部分是那些在有生之年没有使用一元加号的人),但可以说它最清楚、最简洁地表明了我们的意图——它表明我们想要一个int
一个操作数的值,强制另一个值也取消装箱。毫无疑问,它也最类似于规则i1 == i2
用于原语的比较int
价值观。我投你一票
i1 == +i2
&i1 > i2
的样式Integer
对象,出于性能和一致性的考虑。它还使代码可移植到原语,而不必更改除类型声明以外的任何内容。使用命名方法似乎给我带来了语义噪音,类似于备受批评的方法bigInt.add(10).multiply(-3)
风格。hvvq6cgz2#
因为比较方法必须基于类型int(x==y)或类integer(x.equals(y))和右运算符来完成
9vw9lbht3#
我们应该始终使用equals()方法来比较两个整数。这是推荐的做法。
如果我们使用==比较两个整数,由于jvm的内部优化,这将适用于特定范围的整数值(从-128到127的整数)。
请参见示例:
案例1:
整数a=100;整数b=100;
在上面的例子中,jvm使用缓存池中的a和b的值,并返回integer对象的相同对象示例(因此内存地址),我们得到两者相等。这是jvm对某些范围值所做的优化。
案例2:在本例中,a和b不相等,因为它的范围不在-128到127之间。
整数a=220;整数b=220;
正确的方法:
我希望这有帮助。
9bfwbjaz4#
否,==between integer,long等将检查引用相等性-即。
这将检查
x
以及y
指的是同一个对象而不是相等的对象。所以
保证打印
false
. “小”自动装箱值的实习可能会导致棘手的结果:这将打印
true
根据拳击规则(jls第5.1.7节)。它仍然是引用相等,但是引用真正相等。如果要装箱的值p是int类型的整数文本,介于-128和127之间(包括-128和127)(§3.10.1),或布尔文字真或假(§3.10.3),或介于“\u0000”和“\u007f”之间的字符文字(§3.10.4),然后让a和b是p的任意两个装箱转换的结果。通常情况是a==b。
我个人会使用:
或
正如您所说,对于 Package 器类型之间的任何比较(
Integer
,Long
等等)和数字类型(int
,long
etc)取消 Package 类型值的装箱,并将测试应用于所涉及的原语值。这是二进制数字提升的一部分(jls第5.6.2节)。查看每个操作员的文档,看看是否应用了它。例如,从
==
以及!=
(jls 15.21.1):如果相等运算符的操作数都是数字类型,或者一个是数字类型,另一个是可转换的(§5.1.8)对于数字类型,对操作数执行二进制数字提升(§5.6.2).
以及
<
,<=
,>
以及>=
(jls 15.20.1)数值比较运算符的每个操作数的类型必须是可转换的类型(§5.1.8),否则会发生编译时错误。对操作数执行二进制数字提升(§5.6.2). 如果操作数的提升类型是int或long,则执行有符号整数比较;如果此提升类型是float或double,则执行浮点比较。
请注意,在两种类型都不是数字类型的情况下,这些都不被视为一部分。
nxowjjhe5#
此方法使用空检查比较两个整数,请参阅测试
gijlo24d6#
==
仍将测试对象相等。然而,很容易被愚弄:你的例子与不等式将工作,因为他们不是在对象上定义。然而,随着
==
比较时,仍将检查对象相等性。在这种情况下,当您从装箱的基本体初始化对象时,将使用相同的对象(对于a和b)。这是一个很好的优化,因为基本box类是不可变的。oogrdqng7#
==
但是,在编写以下代码时,检查引用是否相等:java非常聪明,可以重用同一个不可变的
a
以及b
,所以这是真的:a == b
. 出于好奇,我写了一个小例子来说明java停止优化的地方:当我编译并运行这个(在我的机器上)时,我得到:
mqkwyuun8#
在我的情况下,我不得不比较两个
Integer
在他们两个都可以平等的地方null
. 搜索了类似的主题,没有找到任何优雅的东西。提出了一个简单的实用函数。lstz6jyr9#
由于java 1.7,您可以使用objects.equals:
如果参数彼此相等,则返回true,否则返回false。因此,如果两个参数都为null,则返回true;如果只有一个参数为null,则返回false。否则,通过使用第一个参数的equals方法来确定相等性。
polhcujo10#
打电话
大部分时间都能用,但不能保证总是能用,所以不要用。
比较两个整数类是否相等的最正确方法是调用:
你也可以用这种方式,这是稍微快一点。
在我的机器上,使用第一种方法990亿次操作花费了47秒,使用第二种方法花费了46秒。您需要比较数十亿个值才能看到任何差异。
请注意,“a”可能为空,因为它是一个对象。以这种方式进行比较不会导致空指针异常。
要比较大于和小于,请使用