我知道如果你比较一个装箱的原语Integer和一个常量,比如:

Integer a = 4;
if (a < 5)

A将自动被打开,比较将会起作用。

但是,当您比较两个带框的整数并希望比较相等或小于/大于时会发生什么?

Integer a = 4;
Integer b = 5;

if (a == b)

上面的代码是否会检查它们是否是同一个对象,或者在这种情况下它会自动开箱吗?

是什么:

Integer a = 4;
Integer b = 5;

if (a < b)

?


当前回答

No, == Integer, Long etc将检查引用是否相等。

Integer x = ...;
Integer y = ...;

System.out.println(x == y);

这将检查x和y是否指向相同的对象,而不是相同的对象。

So

Integer x = new Integer(10);
Integer y = new Integer(10);

System.out.println(x == y);

保证打印为false。“小”自动装箱值的实习可能会导致棘手的结果:

Integer x = 10;
Integer y = 10;

System.out.println(x == y);

根据装箱规则(JLS第5.1.7节),这将输出true。它仍然使用了引用相等,但是引用实际上是相等的。

如果被装箱的值p是一个int类型的整型字面值 -128和127包括(§3.10.1),或布尔字面值真或假(§3.10.3),或'\u0000'和'\u007f'之间的字符字面值 包含(§3.10.4),则设a和b是任意两个装箱的结果 a == b总是成立的。

我个人会使用:

if (x.intValue() == y.intValue())

or

if (x.equals(y))

正如您所说,对于包装器类型(Integer, Long等)和数字类型(int, Long等)之间的任何比较,包装器类型值将被打开,测试将应用于涉及的原语值。

这是二进制数字提升的一部分(JLS第5.6.2节)。查看每个操作符的文档,看看它是否适用。例如,从文档For ==和!= (JLS 15.21.1):

如果一个等式的操作数 运算符都是数值类型或 一个是数字类型,另一个是数字类型 是否可转换(§5.1.8)为数字 类型,二进制数字提升是 在操作数上执行(§5.6.2)。

and <, <=, > and >= (JLS 15.20.1)

a的每个操作数的类型 数值比较运算符必须是 可转换(§5.1.8)的类型 基元数字类型 发生编译时错误。二进制 上执行数字提升 操作数(§5.6.2)。如果升职了 操作数的类型是int或long, 那么有符号整数比较是 执行;如果此提升类型为 Float或double,然后是浮点数 进行比较。

请注意,在两种类型都不是数字类型的情况下,这些都不会被认为是情况的一部分。

其他回答

No, == Integer, Long etc将检查引用是否相等。

Integer x = ...;
Integer y = ...;

System.out.println(x == y);

这将检查x和y是否指向相同的对象,而不是相同的对象。

So

Integer x = new Integer(10);
Integer y = new Integer(10);

System.out.println(x == y);

保证打印为false。“小”自动装箱值的实习可能会导致棘手的结果:

Integer x = 10;
Integer y = 10;

System.out.println(x == y);

根据装箱规则(JLS第5.1.7节),这将输出true。它仍然使用了引用相等,但是引用实际上是相等的。

如果被装箱的值p是一个int类型的整型字面值 -128和127包括(§3.10.1),或布尔字面值真或假(§3.10.3),或'\u0000'和'\u007f'之间的字符字面值 包含(§3.10.4),则设a和b是任意两个装箱的结果 a == b总是成立的。

我个人会使用:

if (x.intValue() == y.intValue())

or

if (x.equals(y))

正如您所说,对于包装器类型(Integer, Long等)和数字类型(int, Long等)之间的任何比较,包装器类型值将被打开,测试将应用于涉及的原语值。

这是二进制数字提升的一部分(JLS第5.6.2节)。查看每个操作符的文档,看看它是否适用。例如,从文档For ==和!= (JLS 15.21.1):

如果一个等式的操作数 运算符都是数值类型或 一个是数字类型,另一个是数字类型 是否可转换(§5.1.8)为数字 类型,二进制数字提升是 在操作数上执行(§5.6.2)。

and <, <=, > and >= (JLS 15.20.1)

a的每个操作数的类型 数值比较运算符必须是 可转换(§5.1.8)的类型 基元数字类型 发生编译时错误。二进制 上执行数字提升 操作数(§5.6.2)。如果升职了 操作数的类型是int或long, 那么有符号整数比较是 执行;如果此提升类型为 Float或double,然后是浮点数 进行比较。

请注意,在两种类型都不是数字类型的情况下,这些都不会被认为是情况的一部分。

从Java 1.7开始,你可以使用Objects.equals:

java.util.Objects.equals(oneInteger, anotherInteger);

如果参数相等则返回true,如果参数为false则返回false 否则。因此,如果两个参数都为空,则返回true 如果恰好有一个参数为null,则返回false。否则, 等号是用第一个的等号法来确定的 论点。

因为比较方法必须基于类型int (x==y)或类Integer (x= (y)),并使用正确的操作符:

public class Example {

    public static void main(String[] args) {
        int[] arr = {-32735, -32735, -32700, -32645, -32645, -32560, -32560};

        for(int j=1; j<arr.length-1; j++)
            if((arr[j-1] != arr[j]) && (arr[j] != arr[j+1]))
                System.out.println("int>" + arr[j]);

        Integer[] I_arr = {-32735, -32735, -32700, -32645, -32645, -32560, -32560};

        for(int j=1; j<I_arr.length-1; j++)
            if((!I_arr[j-1].equals(I_arr[j])) && (!I_arr[j].equals(I_arr[j+1])))
                System.out.println("Interger>" + I_arr[j]);
    }
}

我的意见是,在检查值是否相等时,使用一元+来触发对其中一个操作数的开箱操作,否则只需使用数学操作符。基本原理:

已经提到,Integer的==比较是恒等比较,这通常不是程序员想要的,其目的是做值比较;尽管如此,我还是做了一些关于如何最有效地进行比较的科学研究,包括代码的紧凑性、正确性和速度。

我用了一些常用的方法:

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只是触发标识比较,这是比较值的不正确方式。

由于equals()会产生开销(它必须执行instanceof和未检查的强制转换),方法2-4将以完全相同的速度工作,在紧循环中使用时明显优于方法1,因为HotSpot不太可能优化出强制转换和instanceof。

它与其他比较操作符(例如</>)非常相似——它们将触发开箱,而使用compareTo()不会——但这一次,操作由HS高度优化,因为intValue()只是一个getter方法(被优化的主要候选方法)。

In my opinion, the seldom used version 4 is the most concise way - every seasoned C/Java developer knows that unary plus is in most cases equal to cast to int/.intValue() - while it may be a little WTF moment for some (mostly those who didn't use unary plus in their lifetime), it arguably shows the intent most clearly and most tersely - it shows that we want an int value of one of the operands, forcing the other value to unbox as well. It is also unarguably most similar to the regular i1 == i2 comparison used for primitive int values.

对于Integer对象,我的投票是i1 == +i2 & i1 > i2风格,这是出于性能和一致性的考虑。它还使代码可以移植到原语,而不需要更改类型声明以外的任何内容。对我来说,使用命名方法似乎引入了语义噪声,类似于备受批评的bigInt.add(10).multiply(-3)风格。

我们应该总是使用equals()方法来比较两个整数。这是推荐的做法。

如果我们使用==比较两个整数,由于JVM的内部优化,这将适用于一定范围的整数值(从-128到127的整数值)。

请看例子:

案例1:

Integer a = 100;
Integer b = 100;

if (a == b) {
  System.out.println("a and b are equal");
} else {
  System.out.println("a and b are not equal");
}

在上述情况下,JVM从缓存池中使用a和b的值,并返回相同的对象实例(因此内存地址)的整数对象,我们得到两者相等。它是JVM为特定范围值所做的优化。

情况2:在这种情况下,a和b不相等,因为它没有从-128到127的范围。

Integer a = 220;
Integer b = 220;
   
if (a == b) {
  System.out.println("a and b are equal");
} else {
  System.out.println("a and b are not equal");
}

正确的方法:

Integer a = 200;             
Integer b = 200;  
System.out.println("a == b? " + a.equals(b)); // true