views:

169

answers:

2

Hi,

I'm new to Java and I have a beginner question:

NumberFormat is an abstract class and so I assume I can't make an instance of it. But there is a public static (factory?) method getInstance() that allow me to do

NumberFormat nf = NumberFormat.getInstance();  

I'm quite confuse. I'll be glad if someone could give me hints on:

  1. If there is a public method to get an instance of this abstract class, why don't we have also a constructor?
  2. This is an abstract class ; how can we have this static method giving us an instance of the class?
  3. Why choosing such a design? If I assume it's possible to have an instance of an abstract class (???), I don't get why this class should be abstract at all.

Thank you.

+6  A: 
  1. The class is abstract because it is the base class for every number format in Java (this includes DecimalFormat, for example). Having a constructor for an essentially unknown number format is pretty useless.
  2. The getInstance() method is a so-called factory method. It returns a matching number format for the current locale. Since it is not known what kind of sub-class is required at compile-time, it returns a NumberFormat, however, the instance itself, will be of a sub-type, obviously (since you can't create instances of abstract classes).
  3. This design gives you the flexibility of somehow determining the proper subclass instance to return at runtime without making too much of that design rigid at design/compile time. Static methods are exempt from being abstract so a class can work as both a factory and an abstract supertype for concrete implementations. If this weren't the case you'd probably have a NumberFormatFactory somewhere which would have the factory methods.
Joey
Thank you for your answer. If you could elaborate or give me a link to an example on what you wrote in the 3rd part: "without making too much of that design rigid at design/compile time", it would be great! Regards.
Alex
@Alex: That's the premise of many so-called *design patterns.* In some situations a rigid hierarchy of classes and their relationships is too inflexible to work properly. You either give up flexibility or create yourself maintenance nightmares in case you need to change or extend the design. 600 chars are a bit too short to give a meaningful introduction, but Wikipedia has some info on it (http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29). For many of those the basic principle is not to model relationships between objects as parts of the classes (at compile time) but rather
Joey
... defer this until runtime where you then have much more flexibility in combining several classes into a single, working system. In this case, a constructor would require you to know beforehand which specific subclass of `NumberFormat` you need, because a `NumberFormat` constructor can't create a `DecimalFormat` object. You're abstracting away here the need to know that there *are* subclasses by using a factory method to create the object. The method just creates a subclass of `NumberFormat` which is chosen depending on the locale.
Joey
This is so clear! Thank you very much!
Alex
+7  A: 

Actually what you can obtain from

public static final NumberFormat getInstance()

is something that is ALSO a NumberFormat, but it is a concrete instance of a subclass of it.

You can't in anyway instantiate an abstract class so that method can't return a plain NumberFormat but something that is at least a NumberFormat. In this case the method is used to obtain a default formatter for your locale that will probably be a DecimalFormat or some variations of it

In the documentation of DecimalFormat it states:

To obtain a NumberFormat for a specific locale, including the default locale, call one of NumberFormat's factory methods, such as getInstance(). In general, do not call the DecimalFormat constructors directly, since the NumberFormat factory methods may return subclasses other than DecimalFormat.

To end: you can be sure, if it's abstract, then you cannot instantiate it, neither Java itself can.. since the declaration is missing some parts so it's a real incomplete type.

Jack
Thank you for your answer.
Alex