Is there a better approach to Marker?
Definition: |
---|
Marker Interface in Java is an empty interface without any methods, fields or constants. This is sometimes also referred as tag interface. |
So why Marker interface is used?
Valid question!! It doesn’t solve the purpose of the interface which defines a contract with the classes which implement this interface. The interfaces defines methods without their implementation as it tells the child classes what needs to be done but it leaves the decision on the child classes on how to implement this method. However in case of Marker interface there are no members.
Marker interface is a way to declare the metadata about a class. It tells the JVM that the objects of the classes which implement the marker interface needs to be treated with special care in a different manner. Some of the out of box Marker interfaces are defined in the Java API are:
java.io.Serializable
java.lang.Cloneable
java.util.RandomAccess
java.util.EventListener
We can also create our own version of marker interfaces in the same way as we create other interfaces.
Let’s go in more depth with the Cloneable interface. When the object needs to be cloned in Java we use the Object’s clone() method. However note that this method is not a part of Cloneable interface i.e. when your class implement the Cloneable interface by default the clone method will not be implemented unlike any other standard interfaces. It can be done when we explicitly define it or call the object’s clone method.
Therefore it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.
public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; }
One key point here is that when you try to clone an object using the clone() method you will get CloneNotSupportedException unless you implement the Cloneable interface. JVM is very smart – isn’t it?
Points to note:
As mentioned earlier apart from using the built in marker interfaces we can also create application specific marker interfaces as it is a good way of tagging and logically classify your piece of code. This is mainly useful when trying to create a framework or developing API.
Interesting points:
Runnable is not a Marker interface. Though run is a special instruction to the JVM to start a method but Runnable is not a marker interface because it has a public void run() method inside it.
Problem with the marker interface:
A major problem with marker interfaces is that an interface defines a contract for implementing classes, and that contract is inherited by all subclasses. This means that you cannot un-implement a marker. If you create a subclass that you do not want to serialize (perhaps because it depends on transient state), you must resort to explicitly throwing NotSerializableException.
Now let’s come back to the point. Is it a better approach to use Annotations than Marker interface?
To answer this let’s look into Java Annotations in more details.
Definition: |
---|
Java annotations are special form of syntactic meta-data (data about data) which was introduced in Java 1.5. Like Java Classes, Interfaces even Annotations can be used on several Java elements. |
Unlike the Javadocs Annotations are more feature rich which helps in processing at runtime. Annotations are used in Package or Class declaration, method declaration, field declaration and variable declaration. It reduces coding effort and let’s developers concentrate on the business logic with the ease of development and hence increases automation.
Annotations are demarcated from the standard Java elements by “@” symbol. Whenever the compiler comes across these annotations with any of the Java elements it extracts the information from the annotation and generates the code automatically.
Uses of Annotations:
- Passing information to the compiler – used to detect errors or suppress warnings. E.g. @SuppressWarnings, @deprecated
- Compiler time and deployment time processing – Several tools can process annotation information to generate code XML file etc. Frameworks like Spring, Hibernate make heavy use of annotations.
- Run time processing – These annotations are processed only during the runtime.
In similar way of Marker interfaces we also have marker annotations. A marker annotation does not have any methods or elements. The behaviour is same as the Marker interfaces.
e.g. @Override is a built in Java Marker annotation type that can be implemented to a method to indicate the compiler the compiler that the method overrides a method in a superclass. It does not contain any other program element. If you use this annotation on a method that does not override a superclass method, the compiler issues a compilation error to alert you to this fact. This annotation type guards the programmer against making a mistake when overriding a method as it is quite possible that the developers might actually overload a method in the super class rather than overriding.
It seems annotation is a better choice than the marker interface as the same effect can be achieved by the annotations.
- It can mark variables, methods, and/or classes.
- It can mark any class specifically, or via inheritance. A marker interface will mark all subclasses of the marked class. E.g. if we have to mark a class non serializable then we have to specifically mark it is as transient. It might be a debatable one as annotations not are not sub classable might be either an advantage or a disadvantage. Annotations are not inherited by default – isAnnotationPresent() tells you if the annotation is present on that particular class, but not if it’s present on a superclass or superinterface. So if you, as the implementer of whatever special functionality the annotation is intended to confer, want the annotation to behave as if it’s inherited – you have to check isAnnotationPresent() on not just this class, but every superclass, and every superinterface.
- You can add data to the mark. In other words, an annotation that is not blank has value — in that you are marking with more than just type.
So each one of them having certain advantage and disadvantage I personally feel that the decision on whether to use marker interface or marker annotation should to be left with the developers as they have to decide considering the situation on the ground and judge on the advantages and disadvantages of both of them and decide on what suits the requirement the best.
Reference: Is there a better approach to Marker? from our JCG partner Mainak Goswami at the Idiotechie blog.