Java中的Marker接口
Java中的Marker接口是带有空主体的接口。Marker接口不包含常量或者方法。 Java中Marker接口的示例是
- java.util.RandomAccess
- java.rmi.Remote
- java.io.Serializable
- java.lang.Cloneable
如果我们在JDK中看到Cloneable接口的代码,则如下所示。
public interface Cloneable { }
如我们所见,接口中没有方法或者常量,只有空的主体使Cloneable成为Java中的Marker接口。
标记界面增加了特殊行为
由于Marker接口是一个空接口,因此没有实现方法。用于指示实现Marker接口的类属于该类型,但是Marker接口本身不添加任何行为(因为它没有实现方法)。
在大多数情况下,实现Marker接口的类仅表示应将某些特殊行为添加到该类,因为它属于该类型。例如,如果我们阅读了Java-中某些Marker接口的说明,
可序列化–通过实现java.io.Serializable接口的类来启用类的可序列化性。未实现此接口的类将不会对其状态进行序列化或者反序列化。
在Java中实现SerializableMarker接口的类具有被序列化的行为。该类本身对此行为不做任何事情,它是Java中的ObjectOutputStream类,其中使用instanceof运算符检查对象的类型是否为Serializable。如果类型为Serializable,则仅对象被序列化。
else if (obj instanceof Serializable) { writeOrdinaryObject(obj, desc, unshared); }
Cloneable –类实现Cloneable接口,以向Object.clone()方法指示该方法为该类的实例进行逐域复制是合法的。
在这里再次可以看到,该类仅实现了CloneableMarker接口来添加克隆行为,对象克隆的实际行为由本机方法Object.clone()提供。
RandomAccess – List实现使用的Marker接口,指示它们支持快速(通常为恒定时间)随机访问。鼓励泛型列表算法在应用算法之前检查给定列表是否是此接口的实例。
再次在这里我们可以看到List实现实现了Marker接口RandomAccess来添加快速随机访问的行为。在通用列表类AbstractList中,我们将找到对此类型的检查,例如
this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex)
用户定义的标记界面(自定义标记界面)
我们也可以使用Java创建自己的自定义Marker接口。不需要太多,只需创建一个空主体的界面即可。
public interface MyMarker { }
然后可以用来定义类型。
public class MyMarkerImpl implements MyMarker { public void display() { System.out.println("display method of MyMarkerImpl"); } }
然后,我们可以使用instanceof运算符检查MyMarker类型的对象,同时为该Marker接口类型的对象提供一些特殊的行为。在该类中,还传递了另一个类MyClass的对象,该类未实现Marker接口MyMarker。在这种情况下,将引发异常。
public class Behavior { public static void main(String[] args) { MyMarker myObj = new MyMarkerImpl(); MyClass obj = new MyClass(); addSpecialBehavior(myObj); addSpecialBehavior(obj); } public static void addSpecialBehavior(Object obj) { if(obj instanceof MyMarker) { System.out.println("Adding special behavior to the object"); } else { throw new IllegalArgumentException("Object not of type MyMarker"); } } }
输出:
Adding special behavior to the object Exception in thread "main" java.lang.IllegalArgumentException: Object not of type MyMarker at com.theitroad.programs.Behavior.addSpecialBehavior(Behavior.java:16) at com.theitroad.programs.Behavior.main(Behavior.java:9)