Contents | Prev | Next | Index

CHAPTER 9

Interfaces


An interface declaration introduces a new reference type whose members are constants and abstract methods. This type has no implementation, but otherwise unrelated classes can implement it by providing implementations for its abstract methods.

Java programs can use interfaces to make it unnecessary for related classes to share a common abstract superclass or to add methods to Object.

An interface may be declared to be an direct extension of one or more other interfaces, meaning that it implicitly specifies all the abstract methods and constants of the interfaces it extends, except for any constants that it may hide.

A class may be declared to directly implement one or more interfaces, meaning that any instance of the class implements all the abstract methods specified by the interface or interfaces. A class necessarily implements all the interfaces that its direct superclasses and direct superinterfaces do. This (multiple) interface inheritance allows objects to support (multiple) common behaviors without sharing any implementation.

A variable whose declared type is an interface type may have as its value a reference to any object that is an instance of a class declared to implement the specified interface. It is not sufficient that the class happen to implement all the abstract methods of the interface; the class or one of its superclasses must actually be declared to implement the interface, or else the class is not considered to implement the interface.

9.1 Interface Declarations

An interface declaration specifies a new reference type:

A compile-time error occurs if the Identifier naming an interface appears as the name of any other class or interface in the same package. A compile-time error also occurs if the Identifier naming an interface appears as the name by which a class or interface is to be known via a single-type-import declaration (§7.5.1) in the compilation unit containing the interface declaration. In the example:


class Point { int x, y; }
interface Point { void move(int dx, int dy); }
a compile-time error occurs because a class and an interface in the same package cannot have the same name.

9.1.1 Scope of an Interface Type Name

The Identifier specifies the name of the interface and has as its scope the entire package in which it is declared. This is the same scoping rule as for class type names; see §8.1.1 for an example involving classes.

9.1.2 Interface Modifiers

An interface declaration may be preceded by interface modifiers:

The access modifier public is discussed in §6.6. A compile-time error occurs if the same modifier appears more than once in an interface declaration.

9.1.2.1 abstract Interfaces

Every interface is implicitly abstract. This modifier is obsolete and should not be used in new Java programs.

9.1.3 Superinterfaces

If an extends clause is provided, then the interface being declared extends each of the other named interfaces and therefore inherits the methods and constants of each of the other named interfaces. These other named interfaces are the direct superinterfaces of the interface being declared. Any class that implements the declared interface is also considered to implement all the interfaces that this interface extends and that are accessible to the class.

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

Each InterfaceType in the extends clause of an interface declaration must name an accessible interface type; otherwise a compile-time error occurs.

A compile-time error occurs if there is a circularity such that an interface directly or indirectly extends itself.

There is no analogue of the class Object for interfaces; that is, while every class is an extension of class Object, there is no single interface of which all interfaces are extensions.

The superinterface relationship is the transitive closure of the direct superinterface relationship. An interface K is a superinterface of interface I if either of the following is true:

Interface I is said to be a subinterface of interface K whenever K is a superinterface of I.

9.1.4 Interface Body and Member Declarations

The body of an interface may declare members of the interface:

The scope of the name of a member declared in an interface type is the entire body of the interface type declaration.

9.1.5 Access to Interface Member Names

All interface members are implicitly public. They are accessible outside the package where the interface is declared if the interface is also declared public and the package containing the interface is accessible as described in §7.1.

9.2 Interface Members

The members of an interface are those members inherited from direct superinterfaces and those members declared in the interface.

The interface inherits, from the interfaces it extends, all members of those interfaces, except for fields that it hides and methods that it overrides.

9.3 Field (Constant) Declarations

Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted, but strongly discouraged as a matter of style, to redundantly specify any or all of these modifiers for such fields.

A constant declaration in an interface must not include any of the modifiers synchronized, transient, or volatile, or a compile-time error occurs.

It is possible for an interface to inherit more than one field with the same name (§8.3.3.3). Such a situation does not in itself cause a compile-time error. However, any attempt within the body of the interface to refer to either field by its simple name will result in a compile-time error, because such a reference is ambiguous.

There might be several paths by which the same field declaration might be inherited from an interface. In such a situation, the field is considered to be inherited only once, and it may be referred to by its simple name without ambiguity.

9.3.1 Initialization of Fields in Interfaces

Every field in the body of an interface must have an initialization expression, which need not be a constant expression. The variable initializer is evaluated and the assignment performed exactly once, when the interface is initialized (§12.4).

A compile-time error occurs if an initialization expression for an interface field contains a reference by simple name to the same field or to another field whose declaration occurs textually later in the same interface. Thus:


interface Test {
	float f = j;
	int j = 1;
	int k = k+1;
}
causes two compile-time errors, because j is referred to in the initialization of f before j is declared and because the initialization of k refers to k itself.

(One subtlety here is that, at run time, fields that are initialized with compile-time constant values are initialized first. This applies also to static final fields in classes (§8.3.2.1). This means, in particular, that these fields will never be observed to have their default initial values (§4.5.4), even by devious programs. See §12.4.2 and §13.4.8 for more discussion.)

If the keyword this (§15.7.2) or the keyword super (15.10.2, 15.11) occurs in an initialization expression for a field of an interface, then a compile-time error occurs.

9.3.2 Examples of Field Declarations

The following example illustrates some (possibly subtle) points about field declarations.

9.3.2.1 Ambiguous Inherited Fields

If two fields with the same name are inherited by an interface because, for example, two of its direct superinterfaces declare fields with that name, then a single ambiguous member results. Any use of this ambiguous member will result in a compile-time error. Thus in the example:


interface BaseColors {
	int RED = 1, GREEN = 2, BLUE = 4;
}

interface RainbowColors extends BaseColors { int YELLOW = 3, ORANGE = 5, INDIGO = 6, VIOLET = 7; }
interface PrintColors extends BaseColors { int YELLOW = 8, CYAN = 16, MAGENTA = 32; }
interface LotsOfColors extends RainbowColors, PrintColors { int FUCHSIA = 17, VERMILION = 43, CHARTREUSE = RED+90; }
the interface LotsOfColors inherits two fields named YELLOW. This is all right as long as the interface does not contain any reference by simple name to the field YELLOW. (Such a reference could occur within a variable initializer for a field.)

Even if interface PrintColors were to give the value 3 to YELLOW rather than the value 8, a reference to field YELLOW within interface LotsOfColors would still be considered ambiguous.

9.3.2.2 Multiply Inherited Fields

If a single field is inherited multiple times from the same interface because, for example, both this interface and one of this interface's direct superinterfaces extend the interface that declares the field, then only a single member results. This situation does not in itself cause a compile-time error.

In the example in the previous section, the fields RED, GREEN, and BLUE are inherited by interface LotsOfColors in more than one way, through interface RainbowColors and also through interface PrintColors, but the reference to field RED in interface LotsOfColors is not considered ambiguous because only one actual declaration of the field RED is involved.

9.4 Abstract Method Declarations

The access modifier public is discussed in §6.6. A compile-time error occurs if the same modifier appears more than once in an abstract method declaration.

Every method declaration in the body of an interface is implicitly abstract, so its body is always represented by a semicolon, not a block. For compatibility with older versions of Java, it is permitted but discouraged, as a matter of style, to redundantly specify the abstract modifier for methods declared in interfaces.

Every method declaration in the body of an interface is implicitly public. It is permitted, but strongly discouraged as a matter of style, to redundantly specify the public modifier for interface methods.

Note that a method declared in an interface must not be declared static, or a compile-time error occurs, because in Java static methods cannot be abstract.

Note that a method declared in an interface must not be declared native or synchronized, or a compile-time error occurs, because those keywords describe implementation properties rather than interface properties. However, a method declared in an interface may be implemented by a method that is declared native or synchronized in a class that implements the interface.

Note that a method declared in an interface must not be declared final or a compile-time error occurs. However, a method declared in an interface may be implemented by a method that is declared final in a class that implements the interface.

9.4.1 Inheritance and Overriding

If the interface declares a method, then the declaration of that method is said to override any and all methods with the same signature in the superinterfaces of the interface that would otherwise be accessible to code in this interface.

If a method declaration in an interface overrides the declaration of a method in another interface, a compile-time error occurs if the methods have different return types or if one has a return type and the other is void. Moreover, a method declaration must not have a throws clause that conflicts (§8.4.4) with that of any method that it overrides; otherwise, a compile-time error occurs.

Methods are overridden on a signature-by-signature basis. If, for example, an interface declares two public methods with the same name, and a subinterface overrides one of them, the subinterface still inherits the other method.

An interface inherits from its direct superinterfaces all methods of the superinterfaces that are not overridden by a declaration in the interface.

It is possible for an interface to inherit more than one method with the same signature (§8.4.2). Such a situation does not in itself cause a compile-time error. The interface is considered to inherit all the methods. However, a compile-time error occurs if, for any two such inherited methods, either they have different return types or one has a return type and the other is void. (The throws clauses do not cause errors in this case.)

There might be several paths by which the same method declaration is inherited from an interface. This fact causes no difficulty and never of itself results in a compile-time error.

9.4.2 Overloading

If two methods of an interface (whether both declared in the same interface, or both inherited by a interface, or one declared and one inherited) have the same name but different signatures, then the method name is said to be overloaded. This fact causes no difficulty and never of itself results in a compile-time error. There is no required relationship between the return types or between the throws clauses of two methods with the same name but different signatures.

9.4.3 Examples of Abstract Method Declarations

The following examples illustrate some (possibly subtle) points about abstract method declarations.

9.4.3.1 Example: Overriding

Methods declared in interfaces are abstract and thus contain no implementation. About all that can be accomplished by an overriding method declaration, other than to affirm a method signature, is to restrict the exceptions that might be thrown by an implementation of the method. Here is a variation of the example shown in §8.4.3.1:


class BufferEmpty extends Exception {
	BufferEmpty() { super(); }
	BufferEmpty(String s) { super(s); }
}

class BufferError extends Exception { BufferError() { super(); } BufferError(String s) { super(s); } }
public interface Buffer { char get() throws BufferEmpty, BufferError; }
public interface InfiniteBuffer extends Buffer { char get() throws BufferError; // override }

9.4.3.2 Example: Overloading

In the example code:


interface PointInterface {
	void move(int dx, int dy);
}

interface RealPointInterface extends PointInterface { void move(float dx, float dy); void move(double dx, double dy); }
the method name move is overloaded in interface RealPointInterface with three different signatures, two of them declared and one inherited. Any class that implements interface RealPointInterface must provide implementations of all three method signatures.


Contents | Prev | Next | Index

Java Language Specification (HTML generated by Suzette Pelouch on February 24, 1998)
Copyright © 1996 Sun Microsystems, Inc. All rights reserved
Please send any comments or corrections to [email protected]