class

8.1 Class Declaration

A class declaration specifies a new reference type:

ClassDeclaration:

ClassModifiersopt class Identifier Superopt Interfacesopt ClassBody

If a class is declared in a named package with fully qualified name P, then the class has the fully qualified name P.Identifier. If the class is in an unnamed package, then the class has the fully qualified name Identifier. In the example:

class Point { int x, y; }

the class Point is declared in a compilation unit with no package statement, and thus Point is its fully qualified name, whereas in the example:


package vista;
class Point { int x, y; }

the fully qualified name of the class Point is vista.Point. (The package name vista is suitable for local or personal use; if the package were intended to be widely distributed, it would be better to give it a unique package name.)

A compile-time error occurs if the Identifier naming a class appears as the name of any other class type or interface type declared in the same package.

A compile-time error occurs if the Identifier naming a class is also declared as a type by a single-type-import declaration in the compilation unit containing the class declaration.

In the example:


package test;


import java.util.Vector;
class Point { int x, y; }
interface Point { // compile-time error #1 int getR(); int getTheta(); }
class Vector { Point[] pts; } // compile-time error #2

the first compile-time error is caused by the duplicate declaration of the name Point as both a class and an interface in the same package. A second error detected at compile time is the attempt to declare the name Vector both by a class type declaration and by a single-type-import declaration.

Note, however, that it is not an error for the Identifier that names a class also to name a type that otherwise might be imported by a type-import-on-demand declaration in the compilation unit containing the class declaration. In the example:


package test;


import java.util.*;
class Vector { Point[] pts; } // not a compile-time error

the declaration of the class Vector is permitted even though there is also a class java.util.Vector. Within this compilation unit, the simple name Vector refers to the class test.Vector, not to java.util.Vector (which can still be referred to by code within the compilation unit, but only by its fully qualified name).

8.1.1 Scope of a Class Type Name

The Identifier in a class declaration specifies the name of the class. This class name has as its scope the entire package in which the class is declared. As an example, the compilation unit:


package points;

class Point {
  int x, y;                 // coordinates
  PointColor color;                 // color of this point
  Point next;                 // next point with this color

static int nPoints; }
class PointColor { Point first; // first point with this color PointColor(int color) { this.color = color; } private int color; // color components }

defines two classes that use each other in the declarations of their class members. Because the class type names Point and PointColor have the entire package points, including the entire current compilation unit, as their scope, this example compiles correctly-that is, forward reference is not a problem.

8.1.2 Class Modifiers

A class declaration may include class modifiers.

ClassModifiers:

ClassModifier
ClassModifiers
ClassModifier ClassModifier: one of
public abstract final

A compile-time error occurs if the same modifier appears more than once in a class declaration. If two or more class modifiers appear in a class declaration, then it is customary, though not required, that they appear in the order consistent with that shown above in the production for ClassModifier.

8.1.2.1 abstract Classes

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:

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

8.1.2.2 final Classes

A class can be declared final if its definition is complete and no subclasses are desired or required. A compile-time error occurs if the name of a final class appears in the extends clause of another class declaration; this implies that a final class cannot have any subclasses. A compile-time error occurs if a class is declared both final and abstract, because the implementation of such a class could never be completed.

Because a final class never has any subclasses, the methods of a final class are never overridden.

8.1.3 Superclasses and Subclasses

The optional extends clause in a class declaration specifies the direct superclass of the current class. A class is said to be a direct subclass of the class it extends. The direct superclass is the class from whose implementation the implementation of the current class is derived. The extends clause must not appear in the definition of the class java.lang.Object, because it is the primordial class and has no direct superclass. If the class declaration for any other class has no extends clause, then the class has the class java.lang.Object as its implicit direct superclass.

Super:

extends ClassType

The following is repeated from to make the presentation here clearer:

ClassType:

TypeName

The ClassType must name an accessible class type, or a compile-time error occurs. All classes in the current package are accessible. Classes in other packages are accessible if the host system permits access to the package and the class is declared public. If the specified ClassType names a class that is final, then a compile-time error occurs; final classes are not allowed to have subclasses.

In the example:


class Point { int x, y; }

final class ColoredPoint extends Point { int color; }
class Colored3DPoint extends ColoredPoint { int z; } // error

the relationships are as follows:

The declaration of class Colored3dPoint causes a compile-time error because it attempts to extend the final class ColoredPoint.

The subclass relationship is the transitive closure of the direct subclass relationship. A class A is a subclass of class C if either of the following is true:

Class C is said to be a superclass of class A whenever A is a subclass of C.

In the example:


class Point { int x, y; }

class ColoredPoint extends Point { int color; }
final class Colored3dPoint extends ColoredPoint { int z; }

the relationships are as follows:

A compile-time error occurs if a class is declared to be a subclass of itself. For example:


class Point extends ColoredPoint { int x, y; }
class ColoredPoint extends Point { int color; }

causes a compile-time error. If circularly declared classes are detected at run time, as classes are loaded, then a ClassCircularityError is thrown.

8.1.4 Superinterfaces

The optional implements clause in a class declaration lists the names of interfaces that are direct superinterfaces of the class being declared:

Interfaces:

implements InterfaceTypeList InterfaceTypeList:
InterfaceType
InterfaceTypeList , InterfaceType

The following is repeated to make the presentation here clearer:

InterfaceType:

TypeName

Each InterfaceType must name an accessible interface type, or a compile- time error occurs. All interfaces in the current package are accessible. Interfaces in other packages are accessible if the host system permits access to the package and the interface is declared public.

A compile-time error occurs if the same interface is mentioned two or more times in a single implements clause, even if the interface is named in different ways; for example, the code:


class Redundant implements java.lang.Cloneable, Cloneable {
  int x;
}

results in a compile-time error because the names java.lang.Cloneable and Cloneable refer to the same interface.

An interface type I is a superinterface of class type C if any of the following is true:

A class is said to implement all its superinterfaces.

In the example:


public interface Colorable {
  void setColor(int color);
  int getColor();
}


public interface Paintable extends Colorable { int MATTE = 0, GLOSSY = 1; void setFinish(int finish); int getFinish(); }

class Point { int x, y; }
class ColoredPoint extends Point implements Colorable { int color; public void setColor(int color) { this.color = color; } public int getColor() { return color; } }
class PaintedPoint extends ColoredPoint implements Paintable
{ int finish; public void setFinish(int finish) { this.finish = finish; } public int getFinish() { return finish; } }

the relationships are as follows:

A class can have a superinterface in more than one way. In this example, the class PaintedPoint has Colorable as a superinterface both because it is a superinterface of ColoredPoint and because it is a superinterface of Paintable.

Unless the class being declared is abstract, the declarations of the methods defined in each direct superinterface must be implemented either by a declaration in this class or by an existing method declaration inherited from the direct superclass, because a class that is not abstract is not permitted to have abstract methods.

Thus, the example:


interface Colorable {
  void setColor(int color);
  int getColor();
}



class Point { int x, y; };
class ColoredPoint extends Point implements Colorable { int color; }

causes a compile-time error, because ColoredPoint is not an abstract class but it fails to provide an implementation of methods setColor and getColor of the interface Colorable.

It is permitted for a single method declaration in a class to implement methods of more than one superinterface. For example, in the code:


interface Fish { int getNumberOfScales(); }

interface Piano { int getNumberOfScales(); }

class Tuna implements Fish, Piano {
 // You can tune a piano, but can you tuna fish?
 int getNumberOfScales() { return 91; }
}

the method getNumberOfScales in class Tuna has a name, signature, and return type that matches the method declared in interface Fish and also matches the method declared in interface Piano; it is considered to implement both.

On the other hand, in a situation such as this:


interface Fish { int getNumberOfScales(); }

interface StringBass { double getNumberOfScales(); }

class Bass implements Fish, StringBass {
 // This declaration cannot be correct, no matter what type is used.
 public ??? getNumberOfScales() { return 91; }
}

it is impossible to declare a method named getNumberOfScales with the same signature and return type as those of both the methods declared in interface Fish and in interface StringBass, because a class can have only one method with a given signature. Therefore, it is impossible for a single class to implement both interface Fish and interface StringBass.

8.1.5 Class Body and Member Declarations

A class body may contain declarations of members of the class, that is, fields and methods. A class body may also contain static initializers and declarations of constructors for the class.

ClassBody:

{ ClassBodyDeclarationsopt } ClassBodyDeclarations:
ClassBodyDeclaration
ClassBodyDeclarations ClassBodyDeclaration ClassBodyDeclaration:
ClassMemberDeclaration
StaticInitializer
ConstructorDeclaration
ClassMemberDeclaration:
FieldDeclaration
MethodDeclaration

The scope of the name of a member declared in or inherited by a class type is the entire body of the class type declaration.