使用 == 运算符进行原始和对象比较

Primitive and Object comparison with == operator

我想知道下一个片段的内部 Java 行为是什么:

Long a = 123L;
long b = 123;
System.out.println("a equals b?: " + (a == b));

结果是 true,尽管比较两个 Long 对象将是 false(因为它比较它们的引用)。它正在 Java 将 Long 对象转换为其原始值,因为检测到针对另一个原始对象的 == 运算符?

来自the Java Tutorials

Autoboxing and Unboxing

Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.

Here is the simplest example of autoboxing:

Character ch = 'a';

The rest of the examples in this section use generics. If you are not yet familiar with the syntax of generics, see the Generics (Updated) lesson.

Consider the following code:

List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
    li.add(i);

Although you add the int values as primitive types, rather than Integer objects, to li, the code compiles. Because li is a list of Integer objects, not a list of int values, you may wonder why the Java compiler does not issue a compile-time error. The compiler does not generate an error because it creates an Integer object from i and adds the object to li. Thus, the compiler converts the previous code to the following at runtime:

List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
    li.add(Integer.valueOf(i));

Converting a primitive value (an int, for example) into an object of the corresponding wrapper class (Integer) is called autoboxing. The Java compiler applies autoboxing when a primitive value is:

  • Passed as a parameter to a method that expects an object of the corresponding wrapper class.
  • Assigned to a variable of the corresponding wrapper class. Consider the following method:

    public static int sumEven(List li) { int sum = 0; for (Integer i: li) if (i % 2 == 0) sum += i; return sum; }

Because the remainder (%) and unary plus (+=) operators do not apply to Integer objects, you may wonder why the Java compiler compiles the method without issuing any errors. The compiler does not generate an error because it invokes the intValue method to convert an Integer to an int at runtime:

public static int sumEven(List<Integer> li) {
    int sum = 0;
    for (Integer i : li)
        if (i.intValue() % 2 == 0)
            sum += i.intValue();
        return sum;
}

Converting an object of a wrapper type (Integer) to its corresponding primitive (int) value is called unboxing. The Java compiler applies unboxing when an object of a wrapper class is:

  • Passed as a parameter to a method that expects a value of the corresponding primitive type.
  • Assigned to a variable of the corresponding primitive type.

It is Java converting Long object into its primitive value because detects == operator against another primitive object?

是的。其中一个操作数是原始类型,另一个操作数可通过拆箱转换为原始类型。

JLS section 15.21.1 说(强调我的):

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).

Note that binary numeric promotion performs value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).

此外,重要的是要注意,只有当两个操作数都是对象时,才会执行引用相等。 JLS section 15.21.3 说:

If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.