Interface Declarations in Java

Introduction

The previous post introduced Class Declarations in Java and it is the obvious next step to understand the Interface Declarations in Java after that.

So, here is an insight to Interfaces in Java. Interfaces are considered as the way to achieve multiple inheritance in Java. We will certainly talk about that part in the coming sections.

This post will introduce you to Interfaces and will also mention about the Annotations, which are different categories of interfaces and an important feature of the language.

Multiple Inheritance

Multiple Inheritance is a language construct which allows one declared Type (class or interface) to inherit its feature from one or more declared Types(classes or interfaces). As we know from the previous post that Java supports only one Type name in the extends clause, which limits the capabilities of inheriting from multiple classes.

We also noticed that the implements clause allows multiple Type names, hence our declared Type can implement multiple interfaces.

What is the direct impact of this limitation?
We know that the fields in the classes define the features of the class and the methods in the classes or interfaces define the behavior of the class. Which means that a new declared Type can inherit features from only one parent but can inherit behavior from multiple parents.

Of course we can argue about inheriting features from multiple parents with the help of multi level inheritance which is true. But by the nature of inheritance it is still from one parent.


Production Rule for Interface Declaration

The production rule more or less looks same as the one for class declarations, just for some clarity here it is:

NormalInterfaceDeclaration:
InterfaceModifiersopt interface Identifier TypeParametersopt ExtendsInterfacesopt InterfaceBody

If you closely observe, the differences here are:

  • The keyword used for declaring interfaces is interface
  • It has optional ExtendsInterfaces. This means that an interface can optionally extend multiple interfaces.
  • Also, an interface cannot implement any interface or extend any class

Apart from these differences, almost everything remains same as the class declaration.

Marker Interfaces

There is a possibility to declare an interface with an empty body. Such an interface is called a Marker Interface. These kind of interfaces are mostly used for marking a declared type (class) for certain identification purposes.

For e.g: The Serializable interface is a marker interface and it marks all the classes for serialization. Any class which implements this interface can be serialized and subsequently all its sub types will be serializable. Any class which doesn’t implement Serializable will not have any of its state serialized or de-serialzed.

Similarly Cloneable is another marker interface and it marks all the classes eligible for cloning. Any class that implements this interface must override the protected clone(){ } method with a public clone(){ } method.

Few properties of an Interface

Interface Level Properties

  1. An interface is always meant to be implemented, so it cannot be final.
  2. A top level interface cannot be private or protected because of accessibility issues. They are rendered useless and cannot be implemented if declared protected or private.
  3. An interface is always an incomplete definition in terms of its behavior, hence it is abstract .

Member Level Properties

  1. Interfaces declare methods and do not provide an implementation to any of these methods, hence the methods need to be implicitly abstract.
  2. Interface fields and methods must have the public access modifiers because they have to be accessible from every package and class.
  3. Interface fields are implicitly static and final. We need them final because many classes may implement the interface and we wont like everyone changing the value of that one variable which is the center of the universe in our application. For the same reason it makes sense to make it static, so that even if you do not have any direct object, you are still able to access it.

Because all fields are final, you must have an initialization expression for each of the fields. However, the initialization expression need not be a constant. As a consequence of this, you can not use forward reference in initializing fields in an interface. Look at the below example from the JLS $9.3.1

The above declaration is a compile time error. It is because the first expression is referencing to a variable j which is not yet initialized. The third expression is referring to the value of k which is yet not initialized.


Annotation Types

Here is the production rule for annotation type declaration:

AnnotationTypeDeclaration:
InterfaceModifiersopt @ interface Identifier AnnotationTypeBody

This means, annotation types cannot extend or implement any class or interface or annotation, neither the annotation type declaration can be generic.

As per the JLS, an annotation type declaration is a special kind of interface declaration. To distinguish an annotation type declaration from an ordinary interface declaration, the keyword interface is preceded by an at-sign @ .

The java.lang.annotation.Annotation is a super interface to all the annotation types as java.lang.Object is a super class to all class declarations.

But! just extending this interface will not make any interface an annotation type. For e.g. the below interface is not a valid annotation type declaration.

If we declare as below, this will be a correct declaration.

As there are marker interfaces, there can be marker annotation types as well.

Members in Annotation Types

Annotation Types can declare classes, interfaces, constants, methods and enums as members. But most of the annotation types only declare no argument methods and these methods cannot have a throws clause.

These methods are called elements of the annotation type and these elements can optionally have default values. Below is an example:



All annotation types inherit all the members in java.lang.annotation.Annotation and the instance methods in java.lang.Object

Conclusion

This post covered the semantics of Interfaces and Annotation Types in sufficient details. Also, we discussed about marker interfaces. In the next post we will discuss more about annotations and how to use them. We will discuss in detail about what an annotation is required for and its primary use case.

Don’t forget to subscribe to TechieMe to get updates on latest posts.