I was going through the Calendar class source code in the Java API, and noticed that a lot of variables, e.g. DAY_OF_MONTH
, YEAR
, etc are declared as static final
. This struck me as odd because I thought the date of a Calendar instance should be (1) specific to that instance, i.e. non-static and (2) changeable (so it can be set). Can anyone clarify? Thanks!
views:
118answers:
4It's a manifest constant. It doesn't refer to any particular day of the month, but to the concept DAY_OF_MONTH.
You use it to specify which element of a date you want to get (or set).
E.g., I want to add (increase the Calendar's date by) one month:
c.add ( Calendar.MONTH, 1 )
I want to add one day:
c.add ( Calendar.DAY_OF_YEAR, 1 ) ;
I'm calling the same function, with the first parameter the manifest constant of the Calendar field I want to increment/decrement by. (Of course, incrementing/decrementing by any particular field may change other fields: If I add one day to December 31 2099, The DAY_OF_MONTH, MONTH and YEAR fields will all be changed.)
The alternative would be to have different setters for each field, e.g,
addMonth( int n ) ;
addDayOfYear( int n);
That would make coding some use cases more tedious however.
The OP asks:
Can anyone walk me through what happens, say, when you invoke cal.set(2010, 8, 2) where cal is a Calendar? What I'd like to know is how the compiler connects 2 to DATE_OF_MONTH, or where that 2 ends up in the heap, or what the qualified variable name is under which that 2 is stored. Thanks all who answered!
The "strict" Object Oriented answers is, "as a client programmer using Calendars rather than implementing them, you shouldn't need to know about the Calendar's internal layout or algorithms".
The real answer is that Calendar is an interface, so any particular implementing class could do these things any number of ways, so long as the implementation adheres to the public interface and the semantics of the Calendar interface.
The actual implementation of, say, GregorianCalendar is probably that internally it holds the date as some number of seconds since some special date, e.g, the linux "era" (1 January 1970) or the first institution of the Gregorian Calendar (15 October 15 1582).
So cal.set(2010, 8, 2)
probably multiples the year by 365 * 24 * 60 * 60, plus any leap years, the 8
is used to find the number of seconds to the end of the seventh month (again, accounting for a leap day, if any), the 2 adds the number of seconds in two days, etc.
DAY_OF_MONTH is just an index that identifies which field of the Calendar record represents, well, the day of the month. That's a constant, and that's why it's a constant.
These are keys to the calendar values. The values are obtained by calling calendar.get(key)
. For example:
int dayOfMonth = concreteCalendar.get(Calendar.DAY_OF_MONTH);
... and if you call myCalendarObject.get(Calendar.DAY_OF_MONTH), then you will get the day of the month corresponding to the date in myCalendarObject, like if it's August 2, you'll get "2".
It might have been more intuitive if they had created functions called "getDayOfMonth", "getMonth", "getYear", and so forth. Maybe this was somehow more efficient to implement, or maybe they were thinking that as the Calendar class is supposed to be extensible to any calendar, so if you wanted to create, say, "MayanCalendar extends Calendar", that you could then define new constants for KATUN and BAKTUN and so forth and it would work with the existing set and get functions.