I have a few questions on NumberFormat that I've come up with while reading Head First Java. NumberFormat form = NumberFormat.getNumberInstance(); num = form.format(i);
This line of code is creating a NumberFormat object with the reference value of form. It doesn't use the "new" operator, but calls a static final method on an abstract class to get one. My problem is this. The method returns a NumberFormat object which I then call the format instance method on. Is that legal? Calling an instance method on an abstract reference? It just bothers me..... Can anyone clear this up? I've been using this stuff for awhile, but had never really thought about what was going on behind the scenes. If NumberFormat wasn't abstract I would be ok, but calling an instance method on an abstract class (which I thought you couldn't instantiate) seems wrong. Thanks... Erik
An abstract class (just like any class, or any interface) defines a type. It is possible to implement a class which has that type (by extending the abstract class, of course.) You're correct in saying that you can't instantiate an instance of an abstract class; but you can instantiate an instance of an object whose type is (includes) that abstract class, and you can refer to that object by a reference whose type is defined by an abstract class. If you have a reference to a NumberFormat object, then all you really know is that the object has the type NumberFormat. You don't know the class of the object. The objects returned by getNumberInstance() will be of some other class which extends NumberFormat. It's irrelevant to you what that class is -- and in fact, it may vary with JDK version, Java vendor, or even over time in a single JVM. More generally, unless you have a reference whose type is a final class, then just having a reference to some type does not mean that you know the class of the object the reference points to. All of the above holds true unchanged, by the way, if you substitute "interface" for "abstract class."
Great question, great answer. You see a similar thing in the "java.sql" package. Many of the useful "classes" are really interfaces, such as Connection, Statement and ResultSet. If you want to see what is the real type of an object, add this to your code:
This prints out the full name (path + class) of the class that is actually instantiated. As Ernest pointed out, you'll get a class that has extended the "NumberFormat" class. In the case of interfaces, it'll be a class that has implemented that interface.
Wayne L Johnson
Joined: Sep 03, 2003
Here's a complete example that shows you what is going on:
Since "AA" is abstract it can never be instantiated. But you can still declare a variable of type "AA" as long as it holds an object of a type that extends "AA". In fact you could declare it as "Object thing = ..." and that would work, but then you couldn't call the "doSomething()" method w/out an explicit cast to type "AA". If you run this you'll see that the resultant class is "AA$BB". This is how Java names inner (nested) classes. [ January 21, 2004: Message edited by: Wayne L Johnson ]
Joined: Jun 13, 2003
Thanks. Ya'll both helped a lot. I'll look more at this tomorrow and I'll be back with a few more questions. Erik