Reputation: 6922
I am just going through a tutorial and the instructor seemed to gloss over something which didn't make sense
In Java if I am looking to instantiate a new Gregorgian Date Object I would use:
GregorianCalendar gc= new GregorianCalendar (2010,1,14);
but if I am looking to use the Data Format object I would use:
DateFormat df = DateFormat.getDateInstance();
I would really like to understand why dateformat doesn't follow the first way of instantiating the class?
How would I know to lookout in future for a similar gotcha?
Upvotes: 3
Views: 195
Reputation: 75426
You should always consult the API documentation to see how you are to use it.
A new X()
always create a new object so if you have multiple places you need it, you end up with multiple X'es which may be inefficient if a single X would do.
The .getDateInstance()
call is a Factory that allow the API to decide by itself whether to return the same X even to multiple callers or a new one to each. For very expensive but reusable/sharable objects this is the typical way you get them.
The Calendar API was donated to Java a very long time ago and is not as well designed as could be. These days the typical response to "I have problem X with Calendar and/or java.util.Date" in java is to use the Joda library which is well designed. For new code using Java 8 or later, use the new java.time classes as commented by Basil Bourque.
Upvotes: 5
Reputation: 340118
The Answer by Thorbjørn Ravn Andersen is correct. Here are some more thoughts.
GregorianCalendar
is one of the terrible date-time classes bundled with the earliest versions of Java, designed by people who did not understand date-time handling.
These classes were years ago supplanted by the modern java.time classes. The GregorianCalendar
class is specifically replaced by ZonedDateTime
.
The java.time classes are designed to be immutable, making them thread-safe.
This means you never use new
. Instead, call factory methods. Read about the naming conventions on such methods.
Let’s capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone). We call ZonedDateTime.now
to capture the current moment. As you can see in the source code, the constructor of ZonedDateTime
is marked private
to prevent us from instantiating via new
. Internally to that class, the factory method performs the new
. You can see for yourself, searching that source code for new ZonedDateTime
.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
By the way, if you must use a GregorianCalendar
to interoperate with old code not yet updated to java.time, you can convert. See new conversion methods added to the old classes.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ;
…and…
GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;
Upvotes: 0
Reputation: 1039
this is because it's an abstract class more info on that can be found here: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
same, look if a class is abstract or not.
Upvotes: 1
Reputation: 403581
The short answer is that the core Java API is poorly designed and inconsistent. There's often no good reason for these inconsistencies, you just need to live with them.
More generally, factory methods like DateFormat.getDateInstance()
allow the API to select different implementation classes depending on the situation, whereas using a constructor directly means there's no such flexibility.
Incidentally, unless you specifically want a GregorianCalendar
, then the recommended method for obtaining one is Calendar.getInstance()
, which will return you a GregorianCalendar
if your locale is appropriate. Other locales will return different Calendar
implementations. This would be consistent with your DateFormat
example.
Upvotes: 3