SCJP: can't widen and then box, but you can box and then widen
Asked Answered
S

5

5

I'm studying for the SCJP exam and I ran into an issue I can't really wrap my head around.

The book says you can't widen and then box, but you can box and then widen. The example for not being able to box is a method expecting a Long and the method being invoked with a byte.

Their explanation is:

Think about it…if it tried to box first, the byte would have been converted to a Byte. Now we're back to trying to widen a Byte to a Long, and of course, the IS-A test fails.

But that sounds like box and then widen and not widen and then box to me.

Could anyone clarify the whole box and widen vs widen and box for me because as it stands the book isn't exactly clear on the issue.

Edit: To clarify: I'm talking about pages 252 and 253 of the SCJP sun certified programmer for java 6 book. http://books.google.be/books?id=Eh5NcvegzMkC&pg=PA252#v=onepage&q&f=false

Semitics answered 15/9, 2010 at 19:2 Comment(1)
"But that sounds like box and then widen" you need to understand that what's happening in this example is first the conversion byte to long, so it's a widen first. It's still not clear?Winny
B
4

the language is confusing.

Basically you can't go in this fashion:
byte -> Byte -> Long
because Byte and Long don't share an is-a relationship.
So, it tries to do this:
byte -> long -> Long
But it can't do that either(apparently due to compiler limitations). So, it fails and throws an error.

But, on the other hand you CAN do this:
byte -> Byte -> Object
because Byte is-an Object.

consider 2 functions and a byte variable:

toLong(Long x)
toObject(Object x)
byte b = 5;

Then this statement will be illegal:
toLong(b);
// because b -> new Byte(b) -> new Long(new Byte(b)) is illegal.
AND byte -> long -> Long can't be done due to compiler limitations.

but this statement is legal:
toObject(b);
// because b -> new Byte(b) -> new Object(new Byte(b)) is legal.

Braeunig answered 31/10, 2010 at 17:22 Comment(0)
Y
4

The reason why "widening then boxing" is not allowed may be because of the following reason (page 249 of the SCJP book):

Java 5's designers decided that the most important rule should be that preexisting code should function the way it used to, so since widening capability already existed,a method that is invoked via widening shouldn't lose out to a newly created method that relies on boxing

Yacketyyak answered 10/11, 2012 at 9:8 Comment(0)
C
3

Basically what this means is that widening only works with primitive types, not the wrappers. If you box first, you get a wrapper (byte -> Byte). But the wrappers - Byte, Double, Float, Integer, Long and Short do not have any inheritance relationship (IS-A). A Long parameter can't accept a Byte for instance.

So you must widen first (byte -> long) and then box (long -> Long).

Costive answered 15/9, 2010 at 19:33 Comment(2)
The reason behind that widening not being possible is clear to me. After all a Byte is not an instanceof a Long. But they don't seem to make the distinction. I know it's easy to accept widening and then boxing not being allowed as a rule but I'm quite curious as to the why.Semitics
I think the language of the book is confusing. But the above is what is probably meant. There is no concept of widening for wrappers i.e. Byte -> Short -> Integer -> Long -> Double, so the question of widening after boxing doesn't arise in this context.Costive
C
1

It isn't a widening because Byte doesn't fit in a Long. That's why it doesn't works.

You can box into a Byte and then widen into an Object or a Number.

As your book says :

we're back to trying to widen a Byte to a Long


In your case, I suppose the code looks like this :

byte b = 1;
Long l = b;

b is changed into a Byte (boxing first) but can't be changed into a Long because Byte isn't a subclass of Long.

In more steps :

byte b = 1;
Byte byteB = b; //works
Long l = byteB; //doesn't work
Chapnick answered 15/9, 2010 at 19:9 Comment(7)
But for a byte to be a Byte it would need to be boxed first and it's talking about widening and then boxing not being allowed... I mean if I manually widen the byte to a long I can invoke a Long function using the second. So did the developers just disallow it because it could be too slow? I can't just wrap my head around the reasoning why boxing and then widening would be allowed but widening and boxing not.Semitics
The part of the book you're reading isn't about "widening and boxing", it's about an example of what "boxing and widening" isn't. This is just before your quote "Why didn't the compiler try to use the box-then-widen logic when it tried to deal with the WidenAndBox class?"Chapnick
Actually it seems to talk about both. Or I'm really misinterpretting it. I updated my original post with a link to the page.Semitics
You're misinterpreting it. "Widening and boxing" doesn't work. This is a fact, no really much more to say about it. The part of the book you're reading is really concentrated on the "boxing/widening" operation. java.sun.com/docs/books/jls/third_edition/html/…Chapnick
I've read that it states that, the question is more about the WHY. boxing and then widening is possible, but the other way around isn't. I mean if I were to do it manually with <code>byte b = 1; long l = (long)b;</code> Which is a widening and then an invocation of a Long method with l would be possible. And the net result is a widening followed by a boxing.Semitics
Because these two solutions are exclusive. How would the compiler choose a solution between Long l = b and Object o = b ? What would it need to do here ? Two different solutions for a similar code. So one solution has been chosen, l = b won't work but o = b will.Chapnick
I don't see a reason for them being mutually exclusive. Although one would have to be a bit more careful then.Semitics
B
1

In essence the rules stand that you can box then widen but not widen then box. However if boxing then widening then the class being widened must be in the same inheritance tree as the class you are widening to.

Whilst the example shown is trying to box then widen, the reason it is invalid is because Byte is not a Long, ie they are not in the same inheritance tree. However if the example used Byte and Numeric, then you it would be valid to Box byte to Byte and then widen Byte to Numeric as Byte IS-A Numeric (they ARE in the same inheritance tree)

Beseech answered 28/1, 2011 at 8:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.