Java中的标记接口?

问题

我被告知Java中的Marker接口是一个空接口,用于向编译器或JVM发信号通知必须以特殊方式处理实现此接口的类的对象,如序列化,克隆等。

但最近我了解到它实际上与编译器或JVM无关。例如,在Serializable接口的情况下,方法writeObject(Object)ofObjectOutputStream具有类似于instanceOf Serializable的内容,以检测该类是否实现Serializable并且相应地抛出NotSerializableException。一切都在代码中处理,这似乎是一个设计模式,所以我认为我们可以定义自己的标记接口。

现在我怀疑了:

  • 上面提到的标记接口的定义在第一点是错误的吗?那么我们如何定义Marker接口呢?
  • 而不是使用instanceOf运算符为什么该方法不能像writeObject(Serializable)那样有一个编译时类型检查而不是运行时?
  • 注释如何比标记接口更好?

#1 热门回答(92 赞)

  • 上面提到的标记接口的定义在第一点是错误的吗? - 在(1)标记界面必须为空的部分中是正确的,并且(2)实施它意味着对实施类的某些特殊处理。不正确的部分是它暗示JVM或编译器会以不同的方式处理该类的对象:你正确地观察到它是Java类库的代码,将这些对象视为可复制,可序列化等。它具有与编译器或JVM无关。
  • 而不是使用instanceOf运算符为什么该方法不能像writeObject(Serializable)那样有一个编译时类型检查 - 这可以避免在"plain对象"时使用标记接口的名称来污染代码"需要。例如,如果你创建一个需要可序列化的类并且具有对象成员,那么你将被迫在编译时进行强制转换或使对象可序列化。这是不方便的,因为界面没有任何功能。
  • 注释如何比标记接口更好? - 它们可以实现将类的元数据传递给消费者的相同目的,而无需为其创建单独的类型。注释也更强大,让程序员将更复杂的信息传递给"消费"它的类。

#2 热门回答(18 赞)

不可能强制执行SerializableonwriteObject因为非序列化类的子代可以序列化,但是它们的实例可以被上传回父类。因此,保持对不可序列化的引用(如Object)的引用并不意味着引用的实例实际上不能被序列化。例如在

Object x = "abc";
   if (x instanceof Serializable) {
   }

父类(Object)不可序列化,并且将使用其无参数构造函数进行初始化。由x,String引用的值是可序列化的,并且条件语句将运行。


#3 热门回答(5 赞)

Java中的标记接口是没有字段或方法的接口。更简单地说,Java中的空接口称为标记接口。标记接口的示例是Serializable,Cloneable和Remote接口。这些用于向编译器或JVM指示一些信息。因此,如果JVM看到一个类是Serializable,它可以对它进行一些特殊操作。同样,如果JVM看到某些类正在实现Cloneable,它可以执行一些操作来支持克隆。 RMI和Remote接口也是如此。简而言之,标记接口指示编译器或JVM的信号或命令。

上面的内容最初是作为a blog post的副本开始的,但是对语法进行了轻微的编辑。