Philip Mathew
Philip Mathew

Reputation: 261

Java widening conversions

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 and then boxing it. How come Byte b = new Byte(10) won't compile? Why can't the compiler narrow int 10 to byte 10 like it did in the first case?

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

I'm not clear about how this works. Can somebody provide an clear explanation?

Upvotes: 25

Views: 4297

Answers (5)

Sanjay Dutt
Sanjay Dutt

Reputation: 2222

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....

Upvotes: 1

rgettman
rgettman

Reputation: 178263

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;

Upvotes: 20

yshavit
yshavit

Reputation: 43391

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.

Upvotes: 10

NESPowerGlove
NESPowerGlove

Reputation: 5496

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.

Upvotes: 1

rdp
rdp

Reputation: 2088

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.

Upvotes: 1

Related Questions