A marker interface is an interface that contains no method declarations but merely designates (or “marks”) a class that implements the interface as having some property. For example, consider the
You may hear it said that marker annotations (Item 39) make marker interfaces obsolete. This assertion is incorrect. Marker interfaces have two advantages over marker annotations. First and foremost, marker interfaces define a type that is implemented by instances of the marked class; marker annotations do not. Compile-time error detection is the intent of marker interfaces, but unfortunately, the
Another advantage of marker interfaces over marker annotations is that they can be targeted more precisely. If an annotation type is declared with target
Arguably, the
The chief advantage of marker annotations over marker interfaces is that they are part of the larger annotation facility. Therefore, marker annotations allow for consistency in annotation-based frameworks.
Serializable
interface (Chapter 12). By implementing this interface, a class indicates that its instances can be written to an ObjectOutputStream
(or “serialized”).You may hear it said that marker annotations (Item 39) make marker interfaces obsolete. This assertion is incorrect. Marker interfaces have two advantages over marker annotations. First and foremost, marker interfaces define a type that is implemented by instances of the marked class; marker annotations do not. Compile-time error detection is the intent of marker interfaces, but unfortunately, the
ObjectOutputStream.write
API does not take advantage of the Serializable
interface: its argument is declared to be of type Object
, so attempts to serialize an unserializable object won’t fail until runtime.Another advantage of marker interfaces over marker annotations is that they can be targeted more precisely. If an annotation type is declared with target
ElementType.TYPE
, it can be applied to any class or interface. Suppose you have a marker that is applicable only to implementations of a particular interface. If you define it as a marker interface, you can have it extend the sole interface to which it is applicable, guaranteeing that all marked types are also subtypes of the sole interface to which it is applicable.Arguably, the
Set
interface is just such a restricted marker interface. It is applicable only to Collection
subtypes, but it adds no methods beyond those defined by Collection
. It is not generally considered to be a marker interface because it refines the contracts of several Collection
methods, including add
, equals
, and hashCode
. But it is easy to imagine a marker interface that is applicable only to subtypes of some particular interface and does notrefine the contracts of any of the interface’s methods. The chief advantage of marker annotations over marker interfaces is that they are part of the larger annotation facility. Therefore, marker annotations allow for consistency in annotation-based frameworks.
In summary, marker interfaces and marker annotations both have their uses. If you want to define a type that does not have any new methods associated with it, a marker interface is the way to go. If you want to mark program elements other than classes and interfaces or to fit the marker into a framework that already makes heavy use of annotation types, then a marker annotation is the correct choice. If you find yourself writing a marker annotation type whose target is
ElementType.TYPE
, take the time to figure out whether it really should be an annotation type or whether a marker interface would be more appropriate.
In a sense, this item is the inverse of Item 22, which says, “If you don’t want to define a type, don’t use an interface.” To a first approximation, this item says, “If you do want to define a type, do use an interface.”
No comments:
Post a Comment