Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

java

scjp

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

like image 921
Jack Avatar asked Sep 15 '10 19:09

Jack


4 Answers

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.

like image 176
user492883 Avatar answered Nov 01 '22 03:11

user492883


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

like image 24
Bipin Avatar answered Nov 01 '22 02:11

Bipin


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

like image 3
samitgaur Avatar answered Nov 01 '22 01:11

samitgaur


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
like image 1
Colin Hebert Avatar answered Nov 01 '22 01:11

Colin Hebert