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?
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.
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.
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.
The Answer by Thorbjørn Ravn Andersen is correct. Here are some more thoughts.
Avoid legacy date-time classes
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.
Immutable classes
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 ) ;
Related
Since Joda-Time time version 2.0 the static method org.joda.time.DateTime#now() was introduced.
To me it is not clear what is the benefit over the use of new DateTime() (as the code just delegates anyway).
public static DateTime now() {
return new DateTime();
}
Also from the java doc it is not clear to me which one I should prefer.
new DateTime
Obtains a {#code DateTime} set to the current system millisecond time using ISOChronology in the default time zone.
DateTime#now()
Constructs an instance set to the current system millisecond time using ISOChronology in the default time zone.
Can someone explain in which use case which one should be preferred?
new DateTime() requires that a new object be allocated. DateTime.now can reuse a single object across requests, since DateTime instances are immutable. That may cause less memory churn.
But largely I doubt it matters which you use.
The now() method was added to make Joda-Time a little bit closer to java.time.* in Java 8, making the process of conversion a little bit easier. The two methods have exactly the same behaviour.
I don't think there is any difference. Using DateTime.now() looks more elegant than new DateTime() in your code. Here is DateTime.now() source code.
public static DateTime now() {
return new DateTime();
}
While using both classes I found that for creating an object for respective classes
Like
GregorianCalendar today = new GregorianCalendar ();
Calendar today = Calendar.getInstance();
Why it is so? And what is benefits of using one over another?
In most locales, when you write Calendar.getInstance(), it will create a GregorianCalendar object. But there are a few exceptions. Your locale could be set to give you a JapaneseImperialCalendar or a BuddhistCalendar.
If you really need your Calendar to be a GregorianCalendar, then you can explicitly write new GregorianCalendar(). But it's generally considered better form to let the JVM choose the right kind of Calendar based on the locale. That is, you should write Calendar.getInstance(), and be prepared to deal with the possibility of using one of the other calendar types.
There is no logic in the Calendar class for getInstance() to return one of the other types of calendar, such as those used in Iran or Saudi Arabia.
The Calendar Class is nothing but an Abstract Class.The primary reason for making it abstract is that there are multiple types of Calendars available all over the world.
Should org.joda.time.DateTimeZone be defined as static in a class instead of creating a new instance each time it's needed, specially when we're always using the same time zone.
DateTimeZone is thread-safe and immutable so it does not make sense to create a new instance each time. Is my thinking correct?
To add more details, currently my class creates a DateTimeZone object in the constructor of my class, always for the same time zone, so I thought why not make it static instead of creating a new object each time.
DateTimeZone is thread-safe and immutable, and all subclasses must be as well.
See api
So yes. It can be declared as static field.
Should you do it or not, it depends on your class and overall project design. See here why static fields may be evil.
Yes, I think you can create is as a static field - and the link in #Mike's answer tells you about the possible drawbacks of doing so (like possible problems if you want to test your code in a different timezone and so on).
But if your concerns are about performance and memory usage, I wouldn't worry too much about that. It seems that Joda-Time uses an internal cache of DateTimeZone objects:
DateTimeZone zone = DateTimeZone.forID("Europe/London");
DateTimeZone other = DateTimeZone.forID("Europe/London");
System.out.println(zone == other); // true
The code above prints true, which means that both are the same object.
Of course this is an implementation detail (I'm using Joda-Time 2.9.9) and it's not good to rely on such details as these things can change.
Anyway, if you're sure that this timezone will never change, you can make it static. If there's a possibility of having more than one in the future, don't (I wouldn't).
I have the following doubt.
Into my code I have:
Calendar today = Calendar.getInstance();
where today variable is an instance of Calendar so I can't use methods as isLeapYear() on it.
Doing in this way I can perform this method:
GregorianCalendar today = (GregorianCalendar) Calendar.getInstance();
int currentYear = today.get(Calendar.YEAR);
boolean bisestile = today.isLeapYear(currentYear);
My doubt is: exatly why? I am casting the same result instange returned by Calendar.getInstance() to be a GregorianCalendar.
Reading here: http://tutorials.jenkov.com/java-date-time/java-util-calendar.html
it seems to me to understand that The java.util.Calendar class is abstract so I cannot instantiate it so I think that the Calendar.getInstance() automatically return a GregorianCalendar object that have defined the previous isLeapYear() method.
But I can't use it if the object is defined as a simple Calendar and not as a GregorianCalendar.
I know about polymorphism but how exactly works in this specific case?
I think that putting the reference of a GregorianCalendar object (returned by Calendar.getInstance(), is it true?) into a Calendar (I can do it because Calendar is the super type) I can access only to the methods subset defined for this abstract class and not to all the methods defined for the concrete type.
Is it this reasoning correct or am I missing something?
This is polymorphism. Calendar provides an abstract framework, and subclasses like GregorianCalendar provide implementations. In other contexts, understand that Calendar.getInstance() maybe could return (for instance) a Chinese or a Hebrew calendar depending on the locality and system setup.
If what you really want is a GregorianCalendar explicitly, declare the variable as such.
GregorianCalendar cal = new GregorianCalendar();
The Answer by ControlAltDel is correct.
One of the benefits of Object-Oriented Programming is preventing fragile software that breaks after making some change. One of the ways to accomplish that is where we define an interface with one or more implementations. When other code refers to the interface, we can switch out the implementation without breaking the calling code.
So the general rule is to use the highest level of interface that meets your needs.
Example: Collections
For example in Java Collections, use the Collection interface where it meets your needs.
Collection<String> col = new ArrayList<>() ;
Get more specific only if your code requires the additional methods offered by a more specific interface. Here we use List, a sub-interface of Collection that promises additional methods.
List<String> list = new ArrayList<>() ;
Use the ArrayList as an ArrayList only if absolutely necessary, only if that class offers certain methods you require that are not included in its more general interfaces.
ArrayList<String> list = new ArrayList<>() ;
Later we may decide to replace that ArrayList with a LinkedList. Doing so won't break any code that was expecting a List or Collection but would break any calling code that expected an ArrayList specifically.
List<String> list = new LinkedList<>();
Calendar & GregorianCalendar
Similarly, you should use Calendar wherever possible, rather than GregorianCalendar.
Calendar cal = new GregorianCalendar() ;
But if the code absolutely needs the special features of GregorianCalendar then track the object as a GregorianCalendar as shown in the Answer by ControlAltDel.
GregorianCalendar cal = new GregorianCalendar() ;
You can mix this up, using a more-specific type internally and a more-general type externally. If you only need those special GregorianCalendar features inside your own class, but want to expose the calendar to other classes, you can declare the calendar object as a GregorianCalendar as the private member of your class while returning Calendar from a getter method.
…
private GregorianCalendar gregCal = new GregorianCalendar() ;
…
public Calendar getCalendar() {
return this.gregCal ; // Automatically upcast. Appears to any calling code to be a `Calendar`.
}
P.S. The java.util.Calendar & .GregorianCalendar are part of the troublesome old legacy date-time classes now supplanted by the java.time classes built into Java 8 and later. Avoid these old classes.
If you are in Thailand then your code
GregorianCalendar today = (GregorianCalendar) Calendar.getInstance();
will probably fail by throwing a ClassCastException because Calendar.getInstance() can yield the Thai-Buddhist calendar as default in that country. This use-case indicates a strong warning to use Calendar.getInstance() if you are really sitting in Thailand. And then you cannot make your gregorian-based assumptions when you are going to interprete expressions like calendar.get(Calendar.YEAR) (maybe yielding year values like 2543).
Conclusion: When handling date and time, it is much better NOT to use generic interfaces but to be as concrete as possible. I assume you are only interested into the gregorian calendar, so please use:
GregorianCalendar today = new GregorianCalendar();
By the way, the main designers of new java.time-package in Java-8 have also adopted this view to be as concrete as possible:
Most applications should declare method signatures, fields and
variables as LocalDate, not this interface.
Practically this means: You should avoid types like TemporalAccessor, ChronoLocalDate etc., or in old world: Avoid types like java.util.Calendar in favor of concrete types like GregorianCalendar. Polymorphism is not a very good idea in the world of date and time. The concrete types are too different (sometimes in a very subtile way).
What is really meant when using Java Date utilities and something has been deprecated. Does this mean that it is discouraged to use, or does it imply that it is forbidden?
I am guessing it is bad practice to use deprecated methods, but am not sure and wanted to find out.
For example, I am trying to use code such as the following
String date = request.getParameter("date");
model.setDate(new Date(date));
Of course...this is a high level example, but in this situation, my model uses type Date and I need to pull the date off the request as a String and create a date with it.
It works fine how I have it, but it is using a deprecated method.
EDIT - I have gone back and used
SimpleDateFormat formatter = new SimpleDateFormat();
model.setDate(formatter.parse(request.getParameter("date");
The date is in the format MM/DD/YYY like 07/23/2010 but I am getting a ParseException
What could this be from?
You're right that this is bad practice. In almost all cases, deprecated methods tell you what to use instead, and this is no exception (see the Javadocs).
You're trying to create a Date out of a String. But what format is the String in? How should it be parsed? Is it UK or US date format?
The "proper" way to do this is to create an instance of SimpleDateFormat, and call its parse() method passing in your text string. This is guaranteed to work in future, and will be more robust now.
A lot of people have mentioned what Deprecated means, but I don't see any explanation of why these methods are deprecated:
Sun (before they were part of Oracle) deprecated a number of methods in Date to get people to use the Calendar/GregorianCalendar classes for date manipulation instead.
Deprecated objects or methods merely means that if you want to use it in current project, rather use what is recommended. The reason why they still have it is for legacy codes who have used the deprecated method before it was deprecated. Typical example is StringTokenizer vs String.split() method.
For your Date example use SimpleDateFormat to do conversion from String to Date. This allows you to create a date format from which your string date can be parsed to create a Date object.
For your EDIT do this
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
model.setDate(formatter.parse(request.getParameter("date")));
ParseException is caused since you didn't provide a date format structure so the SimpleDateFormat didn't know how your date was structured.
What "Deprecated" Means
You may have heard the term,
"self-deprecating humor," or humor
that minimizes the speaker's
importance. A deprecated class or
method is like that. It is no longer
important. It is so unimportant, in
fact, that you should no longer use
it, since it has been superseded and
may cease to exist in the future.
Java provides a way to express
deprecation because, as a class
evolves, its API (application
programming interface) inevitably
changes: methods are renamed for
consistency, new and better methods
are added, and fields change. But such
changes introduce a problem. You need
to keep the old API around until
developers make the transition to the
new one, but you don't want them to
continue programming to the old API.
The ability to deprecate a class,
method, or member field solves the
problem. Java supports two mechanisms
for deprecation: and an annotation,
(supported starting with J2SE 5.0) and
a Javadoc tag (supported since 1.1).
Existing calls to the old API continue
to work, but the annotation causes the
compiler to issue a warning when it
finds references to deprecated program
elements. The Javadoc tag and
associated comments warn users against
using the deprecated item and tell
them what to use instead.them what to use instead.
http://download-llnw.oracle.com/javase/1.5.0/docs/guide/javadoc/deprecation/deprecation.html
You are right, Its discouraged to use deprecated methods.
This is because these methods may have issues in some situation or have been replaced with more optimistic solutions And also future versions may not support these.
Deprecated means it is planned for removal, because it is buggy or some other bad reason.
It is better to use SimpleDateFormat.parse(); to parse your strings.
In general, when Sun (Oracle, whatever) declares a Java method deprecated, it means that they changed their minds about including it, they discourage you from using it, and they may remove it in some future version. Of course it's likely to be a long time before it gets removed as who knows how much existing code there is out there using it, and what's the point of breaking existing programs just because the inventors of Java think they now have a better idea about how to do something?
Presumably they had a good reason for deprecating something, so you should investigate WHY they say that some newer function is better.
In the case of deprecated Date methods, usually this means that they suggest you now use the Calendar or SimpleDateFormat classes. In your case, probably the latter.
deprecated: something that exists in the current version of Java, but will be removed from future versions at some point.
For your edit, you need to properly initialize the SimpleDateFormat, so it knows what format is coming in. For 07/22/1978 format:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
As other said, the java.util.Date methods were deprecated because the Java team believed they had a better solution in the java.util.Calendar.
Unfortunately that class also proved to be confusing, troublesome, and poorly designed.
So, yes, you should avoid deprecated methods in deference to their replacements. But now those replacements (.Calendar) have a replacement (java.time).
java.time
All the old date-time classes have been supplanted by the java.time framework built into Java 8. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
Use the java.time.format package for parsing and generating String representations of date-time values.
String input = "07/23/2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM/dd/yyyy" );
The new classes include LocalDate for representing a date-only value without time-of-day.
LocalDate localDate = LocalDate.parse( input , formatter );
If you call toString on a LocalDate you get a String representation of the date value in the standard ISO 8601 format, YYYY-MM-DD. To generate a String in other formats, define another formatter. Or call the 'localize' methods to let java.time do the heavy lifting in determining a particular localized format.
Nothing will break if you use them...yet.
But they may well be removed in future versions.