// This page consists of a question about abstract classes and the getInstance( ) method, an answer, and some sample programs.

A.      The question:

After briefly discussing abstract classes last Tuesday, I'm looking back on lab 3  and my implementation of the API class Calendar defined

as:  public abstract class Calendar

 

The following code:

      Calendar dateOfBirth = new Calendar();

 

generates the following compilation error:

 

java.util.Calendar is abstract; cannot be instantiated Calendar dateOfBirth = new Calendar();

                                    ^

But, the API documentation says:  "Calendar's getInstance method returns a Calendar object whose calendar fields have been initialized with the current date and time"

 

The following code compiles and runs:

 

         Calendar dateOfBirth = Calendar.getInstance();

 

Later on, I use dateOfBirth by sending a message to the object

 

         dateOfBirth.set( 1960, 0, 1 );

 

This works just fine.

 

I don't get it.  Using the keyword "new" is an error because an abstract class cannot be instantiated, but using

Calendar.getInstance() creates an object?  Those statements seem contradictory.

 

Furthermore, I thought that an abstract class is actually a superclass, and that the programmer (me) would have to create a subclass that extends the abstract superclass, and that defines the bodies of the abstract methods.  Obviously, I'm not doing that when I use the Calendar class.

 

What is really going on here?

 

 

A.      An answer:

Below are information that I hope will shed some light on your inquiry:

 

a. It's true that an abstract class cannot be instantiated. As you reported, new Calendar() does not work.

 

b. Using a getInstance() method to generate an instance of some class is a "convention" in many Java classes. It's particularly common in many of the cryptography related classes (in javax.crypto), such as CertificateFactory, Cipher, KeyFactory, KeyPairGenerator, KeyStore, MessageDigest, and so on.

 

c. Calendar is not the only abstract class that allows the user to use getInstance() to produce an object of the class. KeyPairGenerator and MessageDigest, for example, are abstract classes with getInstance() methods as well.

 

d. The object returned by the getInstance() method of an abstract class is not an object of that class itself; instead, it is an object of one of its concrete subclasses. For example, the object returned by Calendar.getInstance() is an object of the class GregorianCalendar, which is a concrete subclass of the Calendar class. That means the statement

      Calendar c = Calendar.getInstance();

is the same as

      Calendar c = new GregorianCalendar();

 

As we discussed in class, because GregorianCalendar is a subclass of Calendar, it is ok to assign an object of GregorianCalendar to a variable of its Superclass (polymorphism).

 

e. Unfortunately such information is not made clear in the Java API, but related discussions can be found in the various online forums (like http://www.velocityreviews.com/forums/t129209-newbie-instantiating-of-abstract-methods-calendar.html and http://stackoverflow.com/questions/4961095/help-understanding-abstract-classes-java-calendar-method-getinstance. A sample program is also given in the second link, which illustrates how a getInstance() method of an abstract class returns an object of one of its concrete subclasses. For your convenience, the sample program is copied below:

 

abstract class AbstractParent {

    public static AbstractParent getInstance() {

        // Normally you'd have code to work out which

        // concrete class to actually use

        return new ConcreteChild();

    }

 

    public abstract void sayHello();

}

 

class ConcreteChild extends AbstractParent {

    @Override public void sayHello() {

        System.out.println("Hello from ConcreteChild");

    }

}

 

public class Test {

    public static void main(String[] args) {

        AbstractParent parent = AbstractParent.getInstance();

        parent.sayHello();

    }

}

 

BTW, a related topic to this discussion is the so-called "Factory Method design pattern", which however is beyond the scope of a beginning Java programming class like csci3134. Check some of the online resources to find out more if you're interested.

 

 

B.      Sample programs:

 

กค         AbstractGetInstanceTest.java //The sample program included in the answer above.

 

กค         CalendarExample.java //Another program that illustrates the use of the Calendar class

                                // source: http://www.idevelopment.info/data/Programming/java/date/CalendarExample.java