views:

236

answers:

4

Number n = new Number(5) is illegal, but Number n = 5 isn't. Why?

+25  A: 

Because of autoboxing. 5 is not an object so it is wrapped into an object (Integer in this case), and Integer is a Number.

Bombe
To verify this yourself just add System.out.println(n.getClass().getName());
Buhb
The question was mainly about abstract classes.
Willi
No, it was about “how does `Number n = 5;` work if `Number` is abstract?” See above for how it does. :)
Bombe
+4  A: 

Fundamentally, it's because Number is an abstract class - there is no constructor that corresponds to Number(5), and even if there was you still would not be able to instantiate the class directly because it's abstract.

As Bombe explains, in your second case you're really creating an Integer object* - which, as a subclass of Number, can be assigned to such a variable. And as it's a concrete class you can instantiate it.

*Although in practice it's actually more equivalent to Integer.valueOf(5), which on Sun JREs won't create an additional Integer object but will use a pooled version (like the Flyweight pattern).

Andrzej Doyle
why it must be a static class?
Carlos Heuberger
+1 your answer is way better than Bombe's, he did not even use the word abstract in his answer, that's what the question was about
Willi
@Carlos - I meant *concrete* class, not static; I've fixed this typo ("thinko"?), thanks for pointing it out. AFAIK there's no such thing as a static class per se (ignoring static inner classes which are a separate thing).
Andrzej Doyle
A: 

It shouldn't be. autoboxing is a big mistake.

irreputable
I'd have to disagree. int is the mistake.The language would be simpler everything was defined as an Integer (or Long or whatever subclass of Number.) Then let the compiler optimize it into an int (or whatever primitive.) Of course it would have to handle == in sane manner.
Mr Jacques
+1  A: 

It's similar to how the following would work:

List bob = new ArrayList();

List is an interface, so you can't instantiate it directly. However, you can declare a variable of type List and then assign to it a concrete object that implements that interface. Along the same lines, you can declare a variable of type Number and then assign to it any value object that is a concrete instance of that type. What you have done with the functional code is, for all intents and purposes (due to autoboxing):

Number n = new Integer(5);
RHSeeger