Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the Java JLS specify promotion of primitive wrapper types?

Tags:

java

jls

I am somewhat mystified by the output of this program:

public class xx {
    public static void main(String[] args) throws Exception {
        Number x = false ? new Long(123) : new Integer(456);
        System.out.println(x + " isa " + x.getClass().getName());
    }
}

Here's what it outputs:

456 isa java.lang.Long

It appears the compiler is "promoting" an object of type Integer to Long, just as it would normally promote primitive values. I've never heard of object promotion and this behavior seems very surprising.

My question: is this really correct behavior according to the JLS? If so I'd like to see a reference if possible.

Or is this some kindof autoboxing-gone-wild compiler bug?

I'm using:

java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
like image 972
Archie Avatar asked Jan 20 '16 22:01

Archie


People also ask

Which method return wrapper class object from the primitive value?

The valueOf method returns the wrapper classes from primitive types. int age = 17; double weight = 55.3; String v1 = String. valueOf(age); String v2 = String. valueOf(weight);

Which of the following options are wrapper classes for primitive types?

As the name suggests, wrapper classes are objects encapsulating primitive Java types. Each Java primitive has a corresponding wrapper: boolean, byte, short, char, int, long, float, double. Boolean, Byte, Short, Character, Integer, Long, Float, Double.

What are wrapper class and various conversion methods?

A Wrapper class is a class whose object wraps or contains primitive data types. When we create an object to a wrapper class, it contains a field and in this field, we can store primitive data types. In other words, we can wrap a primitive value into a wrapper class object.


2 Answers

This is actually binary numeric promotion (JLS, Section 5.6.2).

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

  1. If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).

  2. Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

    • If either operand is of type double, the other is converted to double.

    • Otherwise, if either operand is of type float, the other is converted to float.

    • Otherwise, if either operand is of type long, the other is converted to long.

    • Otherwise, both operands are converted to type int.

Binary numeric promotion is performed on the operands of certain operators:

...

  • In certain cases, the conditional operator ? : (§15.25)

So, the operands are unboxed and the 456 gets widened to 456L.

Also, the specific case of Long and Integer is covered explicitly by the JLS Section for the conditional operator, JLS Section 15.25, Table 15.25-C.

bnp(Long,Integer)

where "bnp" means binary numeric promotion. Therefore, the conditional operator expression is of type long, which gets boxed to a Long to be assigned to a Number.

like image 130
rgettman Avatar answered Oct 19 '22 20:10

rgettman


The JLS defines the type of the expression a ? b : c in case b and c are Long and Integer respectively, in this table.

The type of the expression is indeed Long, and there is indeed a binary numeric promotion (bnp) of Integer to Long.

The rule is further detailed here:

The type of a numeric conditional expression is determined as follows:

[...]

Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.

like image 39
JB Nizet Avatar answered Oct 19 '22 20:10

JB Nizet