tl;博士我的意见是+
在检查值相等时使用一元来触发对其中一个操作数的拆箱,否则只需使用数学运算符。理由如下:
前面已经提到,==
比较forInteger
是恒等比较,这通常不是程序员想要的,目的是做值比较;尽管如此,我还是做了一些关于如何最有效地进行比较的科学,无论是在代码紧凑性、正确性和速度方面。
我使用了通常的一堆方法:
public boolean method1() {
Integer i1 = 7, i2 = 5;
return i1.equals( i2 );
}
public boolean method2() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2.intValue();
}
public boolean method3() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2;
}
public boolean method4() {
Integer i1 = 7, i2 = 5;
return i1 == +i2;
}
public boolean method5() { // obviously not what we want..
Integer i1 = 7, i2 = 5;
return i1 == i2;
}
并在编译和反编译后得到此代码:
public boolean method1() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
return var1.equals( var2 );
}
public boolean method2() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method3() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method4() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2.intValue() == var1.intValue() ) {
return true;
} else {
return false;
}
}
public boolean method5() {
Integer var1 = Integer.valueOf( 7 );
Integer var2 = Integer.valueOf( 5 );
if ( var2 == var1 ) {
return true;
} else {
return false;
}
}
如您所见,方法 1 调用Integer.equals()
(显然),方法 2-4 产生完全相同的代码,通过 展开值.intValue()
然后直接比较它们,方法 5 只是触发身份比较,是不正确的方法比较值。
由于(如 JS 已经提到的)equals()
会产生开销(它必须做instanceof
和未经检查的强制转换),方法 2-4 将以完全相同的速度工作,在紧密循环中使用时明显优于方法 1,因为 HotSpot 不是可能会优化演员表 & instanceof
。
它与其他比较运算符(例如<
/ >
)非常相似 - 它们将触发拆箱,而使用compareTo()
不会 - 但这次,HS 高度优化了该操作,因为intValue()
它只是一个 getter 方法(被优化的主要候选者)。
在我看来,很少使用的版本 4 是最简洁的方式——每个经验丰富的 C/Java 开发人员都知道一元加号在大多数情况下等于强制转换为int
/ .intValue()
——而对于某些人(主要是那些没有't 在他们的生命周期中使用一元加号),它可以说是最清楚和最简洁地显示了意图 - 它表明我们想要一个操作数的值,迫使另一个值也取消装箱。毫无疑问,它与用于原始值的常规比较最相似。int
i1 == i2
int
出于性能和一致性的原因,我的投票赞成对象i1 == +i2
的风格i1 > i2
。Integer
它还使代码可移植到原语,而无需更改类型声明以外的任何内容。使用命名方法似乎给我带来了语义噪音,类似于备受批评的bigInt.add(10).multiply(-3)
风格。