An abstract
class is a class that is incomplete, or to be considered incomplete. Only abstract
classes may have abstract
methods, that is, methods that are declared but not yet implemented. If a class that is not abstract
contains an abstract
method, then a compile-time error occurs. A class has abstract
methods if any of the following is true:
abstract
method.abstract
method from its direct superclass.abstract
) and the class neither declares nor inherits a method that implements it.In the example:
abstract class Point { int x = 1, y = 1; void move(int dx, int dy) { x += dx; y += dy; alert(); } abstract void alert(); }
abstract class ColoredPoint extends Point { int color; }
class SimplePoint extends Point { void alert() { } }
a class Point
is declared that must be declared abstract
, because it contains a declaration of an abstract
method named alert
. The subclass of Point
named ColoredPoint
inherits the abstract
method alert
, so it must also be declared abstract
. On the other hand, the subclass of Point
named SimplePoint
provides an implementation of alert
, so it need not be abstract
.
A compile-time error occurs if an attempt is made to create an instance of an abstract
class using a class instance creation expression. An attempt to instantiate an abstract
class using the newInstance
method of class Class
will cause an InstantiationException
to be thrown. Thus, continuing the example just shown, the statement:
Point p = new Point();
would result in a compile-time error; the class Point
cannot be instantiated because it is abstract
. However, a Point
variable could correctly be initialized with a reference to any subclass of Point
, and the class SimplePoint
is not abstract
, so the statement:
Point p = new SimplePoint();
would be correct.
A subclass of an abstract
class that is not itself abstract
may be instantiated, resulting in the execution of a constructor for the abstract
class and, therefore, the execution of the field initializers for instance variables of that class. Thus, in the example just given, instantiation of a SimplePoint
causes the default constructor and field initializers for x
and y
of Point
to be executed.
It is a compile-time error to declare an abstract
class type such that it is not possible to create a subclass that implements all of its abstract
methods. This situation can occur if the class would have as members two abstract
methods that have the same method signature but different return types. As an example, the declarations:
interface Colorable { void setColor(int color); } abstract class Colored implements Colorable { abstract int setColor(int color); }
result in a compile-time error: it would be impossible for any subclass of class Colored
to provide an implementation of a method named setColor
, taking one argument of type int
, that can satisfy both abstract
method specifications, because the one in interface Colorable
requires the same method to return no value, while the one in class Colored
requires the same method to return a value of type int
.
A class type should be declared abstract
only if the intent is that subclasses can be created to complete the implementation. If the intent is simply to prevent instantiation of a class, the proper way to express this is to declare a constructor of no arguments, make it private
, never invoke it, and declare no other constructors. A class of this form usually contains class methods and variables. The class java.lang.Math
is an example of a class that cannot be instantiated; its declaration looks like this:
public final class Math {
private Math() { } // never instantiate this class
. . . declarations of class variables and methods . . .
}
abstract
ClassesIf a class that was not abstract
is changed to be declared abstract
, then pre- existing binaries that attempt to create new instances of that class will throw either an InstantiationError
at link time, or an InstantiationException
at run time (if the method newInstance
of class Class
is used); such a change is therefore not recommended for widely distributed classes.
Changing a class that was declared abstract
to no longer be declared abstract
does not break compatibility with pre-existing binaries.