Java autoboxing rules

2019-01-17 23:40发布

问题:

I am a java novice and so confused by the following example. Is it okay to think that "==" sign will compare the values between Integers and "autoboxed" Integers from int, and compare reference address between Integers?

What about doubles and 0/0?

import edu.princeton.cs.introcs.*;

public class Autoboxing {

    public static void cmp(Integer first, Integer second) {
        if (first < second)
            StdOut.printf("%d < %d\n", first, second);
        else if (first == second)
            StdOut.printf("%d == %d\n", first, second);
        else if (first > second)
            StdOut.printf("%d > %d\n", first, second);
        else
            StdOut.printf("%d and %d are incomparable\n", first, second);
    }

    public static void main(String[] args) {
        cmp(new Integer(42), 43);
        cmp(new Integer(42), new Integer(42));
        cmp(43, 43);
        cmp(142, 142);

        Integer a0 = 1000;
        int b0 = 1000;
        Integer c0 = 1000;
        StdOut.println("a0==b0?" + (a0==b0));
        StdOut.println("a0==c0?" + (a0==c0));
        StdOut.println("b0==c0?" + (b0==c0));

        double x1 = 0.0, y1 = -0.0;
        Double a1 = x1, b1 = y1;
        StdOut.println(x1 == y1);
        StdOut.println(a1.equals(b1));

        double x2 = 0.0/0.0, y2 = 0.0/0.0;
        Double a2 = x2, b2 = y2;
        StdOut.println(x2 != y2);
        StdOut.println(!a2.equals(b2));
    }

}

The result is:

42 < 43
42 and 42 are incomparable
43 == 43
142 and 142 are incomparable
=====
a0==b0?true
a0==c0?false
b0==c0?true
=====
true
false
=====
true
false

回答1:

Unboxing will be happing when arithmetic operators, comparison operators appear.

eg:

Integer a = 10;
a = a+10; //1.unboxing a to int 2.calculate a+10 3.boxing 20 to Integer.
System.out.print(a > 10); //1.unboxing a to int 2. compare

But when == appear, it depends.

If boxing type appear on both side, it will compare the reference.But if base type appear on one side, and the other side is a boxing type, the boxing type will unboxing to base type.

eg:

Integer a = new Integer(129);
Integer b = new Integer(129);
System.out.println(a == b); // compare reference return false
System.out.println(a == 129); // a will unboxing and compare 129 == 129 return true

PS: In Java.lang.Integer Cache to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive) as required by JLS. See source code

So:

Integer a = 127;
Integer b = 127; //cached, the same as b a==b return ture

Integer c = 129;
Integer d = 129; // not cached, c==d return false


回答2:

Here is the Tutorial for Autoboxing and Unboxing.

You can also go through JLS#5.1.7. Boxing Conversion and JLS#5.1.8. Unboxing Conversion

0.0 / 0.0 is NaN you can not compare infinity at least in maths. I guess that is why this comparison does not work.

From JLS #4.2.3. Floating-Point Types, Formats, and Values

Positive zero and negative zero compare equal; thus the result of the expression 0.0==-0.0 is true and the result of 0.0>-0.0 is false

NaN is unordered, so:

  • The numerical comparison operators <, <=, >, and >= return false if either or both operands are NaN (§15.20.1).

  • The equality operator == returns false if either operand is NaN.

  • In particular, (x=y) will be false if x or y is NaN.

  • The inequality operator != returns true if either operand is NaN (§15.21.1).

  • In particular, x!=x is true if and only if x is NaN.

If you check Double#equals method it has two exceptions

also has the value true. However, there are two exceptions:

  • If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false.

  • If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true.

This definition allows hash tables to operate properly.



回答3:

== can only be used for checking if the variables are equal or not if the variables are primitive types. For object variables, == is used to compare the reference of the objects. If you want to compare the values of the objects, use .equals() method.



回答4:

I would not recommend comparing boxed ints with ==, as it works only for some values.



回答5:

Unboxing will happen for arithmetic operators, comparison operators.