Are Java Marker Interfaces Dead?

In earlier versions of Java, Marker Interfaces were the only way to declare metadata about a class. With the advent of annotation in Java 5, it is considered that marker interfaces have now no place. They can be completely replaced by Annotations, which allow for a very flexible metadata capability. Everything that can be done with marker interfaces can be done instead with annotations. In fact, it's now recommended that the marker interface pattern should not be used anymore. Annotations can have parameters of various kinds, and they're much more flexible. We can also see that the examples used in Sun API’s are rather old and that no new ones have been added since after introduce of Annotation. In this post, we will see whether Marker Interfaces can still be used for any reasons.

Purpose of Marker Interfaces in Java

A marker interface is an interface with no method declarations. They just tell the compiler that the objects of the classes implementing the interfaces with no defined methods need to be treated differently. These Marker interfaces are used by other code to test for permission to do something.

marker interfaces list in java

Some well-known examples are

  • java.io.Serializable - object implement it can be serialized using ObjectOutputStream.
  • java.lang.Clonable - objects clone method may be called
  • java.util.RandomAccess- support fast (generally constant time) random access

They are also known as tag interfaces since they tag all the derived classes into a category based on their purpose

Difference between Interface and Marker Interface

Interface in general defines a contract. They represent a public commitment and when implement form a contract between the class and the outside world. On the other hand, an empty interface does not define any members, and as such, does not define a contract that can be implemented.

Normally, when a class implements an interface, it tells something about the instances of the class. It represent an "is a" relationship that exist in inheritance. For example, when a class implements List, then object is a List.

With marker interfaces, this inheritance mechanism usually does not obey. For example, if class implements the marker interface Serializable, then instead of saying that the object is a Serializable, we say that the object has a property i.e. it is Serializable.

Should Avoid Marker Interfaces?

One common problem occurs while using marker interfaces is that when a class implements them, each subclasses inherit them as well. Since you cannot unimplemented an interface in Java, therefore a subclass that does not want to treat differently will still be marked as Marker. For example, Foo implements Serializable, any subclass Bar etc does too as well.

Moreover, there are places in the Sun API’s where such interfaces have been used for messy and varying purposes. Consider Cloneable Marker Interface. If the operation is not supported by an object, it can throw an exception when such operation is attempted, like Collection.remove does when the collection does not support the remove operation (eg, unmodifiable collection) but a class claiming to implement Cloneable and throwing CloneNotSupportedException from the clone() method wouldn't be a very friendly thing to do.

Many developers consider it as broken interface. Ken Arnold and Bill Venners also discussed it in Java Design Issues. As Ken Arnold said,

If I were to be God at this point, and many people are probably glad I am not, I would say deprecate Cloneable and have a Copyable, because Cloneable has problems. Besides the fact that it's misspelled, Cloneable doesn't contain the clone method. That means you can't test if something is an instance of Cloneable, cast it to Cloneable, and invoke clone. You have to use reflection again, which is awful. That is only one problem, but one I'd certainly solve.

Oracle has also reported it as Bug which can refer at https://bugs.openjdk.java.net/browse/JDK-4098033

Are Marker Interfaces end?

Appropriate Use of Marker Interfaces vs Annotation

We usually hear that Marker Interface is now obsolete and it has no place. But, there are situations where they can be handy over using annotations.

Annotations have to be checked at runtime using reflection. Empty interfaces can be checked at compile-time using the type system in the compiler. Compile-time checking can be one of the convincing reason to use such interfaces.

Consider the example below:

@interface
HasTag {
}

@HasTag
public class ClasswithTag {
}

public void performAction(Object obj){
    if (!obj.getClass().isAnnotationPresent(HasTag.class)) {
        throw new IllegalArgumentException("cannot perform action...");
    } else {
        //do stuff as require
    }
}

One problem with this approach is that the check for the custom attribute can occur only at runtime. Sometimes, it is very important that the check for the marker be done at compile-time. Let me refine the above example to use Marker.

interface HasTag {
}

public class ClassWithTag implements HasTag {
}

public void performAction(HasTag ct){
    //do stuff as require
}

Similarly, in the case of the Serializable marker interface, the ObjectOutputStream.write(Object) method would fail at runtime if its argument does not implement the Interface which would not be the case, if ObjectOutputStream had a writeObject(Serializable) method instead.

Marker Interfaces can also be well-integrated in Javadoc where one can promptly see who implements marker interfaces or not by just look it up and see the list of implementing classes.

Moreover, Joshua in Effective Java also recommends using Marker interface to define the type which can result in the very real benefit of compile-time type checking.

1 comment:

  1. Can we create our marker interface .if yes then can you tell me the practical use where custom marker interfaces can be used?

    ReplyDelete