Java widening conversions

后端 未结 5 978
时光取名叫无心
时光取名叫无心 2020-12-28 14:55

I\'m preparing for Java 7 certification and have the following question.

Byte b = 10 compiles ok. Looks like the compiler is narrowing int 10 to byte 10

相关标签:
5条回答
  • 10 is an integer literal, you have to downcast it to pass it to the Byte constructor. There unfortunately is no byte literal syntax to remove the cast either.

    Also how come Long l = new Long(10) compiles ok but Long l = 10 fails?

    Because 10, an integer, can fit into a long with no issues. An integer cannot fit into a byte, so the cast is needed in that case (widening conversion).

    This cast is compile time as well, as it's also a widening conversion. Check out section 5.1.5 in the JLS:

    Widening reference conversions never require a special action at run time and therefore never throw an exception at run time. They consist simply in regarding a reference as having some other type in a manner that can be proved correct at compile time.

    0 讨论(0)
  • 2020-12-28 15:31

    Byte constructor takes either byte type or String type. See this

    Constructor for Long takes long as an argument. Since long can take in integer, it allows it in the constructor.

    0 讨论(0)
  • 2020-12-28 15:36

    i think i have a solution for your problem...

    //constructor for Byte class
    Byte(byte value){
    
    }
    

    There are two rules for java type conversion

    1. Both types are compatible
    2. Destination type is greater than source type

    Now in Your case you trying to convert int into byte which is against our second rule.... but below is the solution

    Byte b = new Byte((byte)10);
    

    Now let's talk about your Second issue...

     Long x = 10;//incompatible type
    

    This is the issue of autoboxing... Now as we all know that autoboxing automatically converted primitive type into it's wrapper class.. But conversion not happens in case of autoboxing means....int is converted into Integer byte is converted into Byte.. Now when you assign int primitive type to Long, it gives you error of incompatible type....... Solution

    Long x = (long) 10;//works fine....
    
    0 讨论(0)
  • 2020-12-28 15:39

    Section 5.2 of the JLS covers the types of conversions that are allowed in assignment contexts.

    Assignment contexts allow the use of one of the following:

    • an identity conversion (§5.1.1)

    • a widening primitive conversion (§5.1.2)

    • a widening reference conversion (§5.1.5)

    • a boxing conversion (§5.1.7) optionally followed by a widening reference conversion

    Additionally,

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

    • A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

    • A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:

      • Byte and the value of the constant expression is representable in the type byte.

      • Short and the value of the constant expression is representable in the type short.

      • Character and the value of the constant expression is representable in the type char.

    Byte b = 10 compiles ok because 10 is a constant expression and is representable as a byte.

    Byte b = new Byte(10) won't compile because 10 is an int literal, and method invocation conversion won't perform primitive narrowing conversions. To get this call to a Byte constructor to compile, you can explicitly cast 10 to byte:

    Byte b = new Byte( (byte) 10);
    

    Long l = new Long(10) compiles because method invocation conversion will perform primitive widening conversions, including from int to long.

    Long l = 10 won't compile, because Java will not specifically allow a widening conversion followed by a boxing conversion, as I discussed in a recent answer. To get this to compile, you can use a long literal, so only boxing is necessary.

    Long l = 10L;
    
    0 讨论(0)
  • 2020-12-28 15:40

    The basic rules are:

    • you can't convert-and-autobox in one step (JLS 5.1.7 defines the boxing conversions, and it doesn't include convert-and-autobox type conversions, so they're not allowed)
    • you can't implicitly narrow a type

    These rules explain why Long l = 10 doesn't work, as well as new Byte(10). The first would require the int literal 10 to be widened to a long and then be boxed, which isn't allowed. (More precisely, it would require a conversion from int to Long, which JLS 5.1.7 doesn't define.) The second would require the int literal 10 to be implicitly narrowed to a byte, which isn't allowed.

    But there are exceptions to the rule. Byte b = 10 is explicitly allowed by JLS 5.2:

    In addition, if the expression is a constant expression (§15.28) 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:
      • Byte and the value of the constant expression is representable in the type byte.

    (some irrelevant parts omitted)

    Lastly, new Long(10) works because the int literal 10 can be automatically widened to a long 10L.

    0 讨论(0)
提交回复
热议问题