Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
574 views
in Technique[技术] by (71.8m points)

java - autoboxing of numeric literals : wrapper initialization vs passing method arguments inconsistency

Please consider 2 cases:

//1
Short s = 10; //obviously compiles    

//2
takeShort(10); //error - int is not applicable

//where:
static void takeShort(Short s) {}

I assume that case 1 is changed by compiler to :

short _temp_s = 10;
Short s = Short.valueOf(_temp_s);

Could you please explain what compiler is trying to do in case 2, so it does not compile ? If it is not trying to apply autoboxing as it does in case 1, then why ?

EDIT

Reference to JSL in johnchen902 answer explains compiler's behaviour.

Still not exactly clear why JLS does not support "A narrowing primitive conversion followed by a boxing conversion" for Method Invocation Conversion as it does in Assignment Conversion for the case of constant expression of type byte, short, char, or int. Any ideas ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Short s = 10;

This is an Assignment Conversion, and 10 is a constant expression. JLS said:

5.2. Assignment Conversion

Assignment conversion occurs when the value of an expression is assigned to a variable: the type of the expression must be converted to the type of the variable.

......

In addition, if the expression is a constant expression of type byte, short, char, or int:

  • A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:
    • Short and the value of the constant expression is representable in the type short.

takeShort(10);

This is a Method Invocation Conversion. JLS said:

5.3. Method Invocation Conversion

Method invocation conversion is applied to each argument value in a method or constructor invocation : the type of the argument expression must be converted to the type of the corresponding parameter.

Method invocation contexts allow the use of one of the following:

  • an identity conversion
  • a widening primitive conversion
  • a widening reference conversion
  • a boxing conversion optionally followed by widening reference conversion
  • an unboxing conversion optionally followed by a widening primitive conversion.

......

If the type of the expression cannot be converted to the type of the parameter by a conversion permitted in a method invocation context, then a compile-time error occurs.

Unlike Assignment Conversion, non of conversion listed above can converts int to Short, so a compile-time error occurs.

Unfortunately some has rejected kiruwka's edit before I can approve it, so I edit it myself

The example of Method invocation conversion:

// takeInteger(int) takeDouble(double) takeObject(Object) takeIntegerObject(Integer)

takeInteger(5);  // an identity conversion
takeDouble(5);   // a widening primitive conversion
takeObject(new Integer(5)); // a widening reference conversion
takeIntegerObject(5);   // a boxing conversion
takeObject(5);   // a boxing conversion followed by widening reference conversion
takeInteger(new Integer(5)); // an unboxing conversion
takeDouble(new Integer(5)); // an unboxing conversion followed by a widening primitive conversion.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...