A specific type is not specified, as it can be any subclass of NumberFormat . It may even depend on the locale you are using. For some locales, you might want ChoiceFormat run correctly, for others, DecimalFormat enough, and for the third locale, they can even return a locale-specific implementation.
The fact that it is not defined more specifically than the abstract base class allows such a change in implementation without changing the method signature for such a change.
You can easily check which particular type is returned by one particular call by calling getClass() on the returned value.
source share