1

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?

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596

3 Answers3

2

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();
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
0

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.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • "The general rule is to use the highest level of interface that meets your needs. " - This can break, see also my answer and given link to the official javadoc of `ChronoLocalDate` (the JSR-310-team has made the opposite statement). The problem is the interpretation of the results of generic interface methods. – Meno Hochschild Aug 29 '16 at 11:36
0

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).

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126