【问题标题】:What is the use of marker interfaces in Java?Java中标记接口的用途是什么?
【发布时间】:2010-12-31 23:58:38
【问题描述】:

当在Serializable之类的标记接口中没有什么要实现的时候,实现它有什么用?

【问题讨论】:

标签: java annotations marker-interfaces


【解决方案1】:

Joshua Bloch:有效的 Java 第 2 版,第 179 页

第 37 条:使用标记接口定义类型

... 你可能会听到它说那个标记 注释(第 35 项)制作标记 接口已过时。这个断言是 不正确。标记接口有两个 优于标记注释。 首先,标记接口 定义一个由实现的类型 标记类的实例;标记 注释没有。的存在 这种类型允许您捕获错误 在编译时你不能 如果您使用了 标记注释....

就我个人而言,我认为我会向 Joshua 在这方面的卓越知识低头。

【讨论】:

  • 问题是,这经常与第 19 条:只使用接口来定义类型相矛盾。 “Serializable”不是一种类型,它是一种属性/行为。
  • 其实连“Serializable”都可以看成一个类型。考虑以下方法签名: public void serialize(Serializable objectToSerialize);在这种情况下,在编译时很明显,只有可序列化的对象才能传递给“序列化”,这对于注解是不可能的。
【解决方案2】:

在 Java 的早期版本中,Marker Interfaces 是声明类元数据的唯一方法。例如,Serializable Marker Interface 让类的作者说他们的类在序列化和反序列化时会正确运行。

在现代 Java 中,标记接口没有位置。它们可以完全由Annotations 代替,这允许非常灵活的元数据功能。如果您有关于某个类的信息,并且该信息永远不会改变,那么注释是一种非常有用的表示它的方式。

【讨论】:

  • 我真的很喜欢注释,但在这种情况下,它们的缺点是检查起来有点复杂(与使用 instanceof 相比)。它们也没有很好地集成在 javadoc 中(查看实现 的快速方法是查找它并查看实现类的列表)。所以我想说他们仍然有一席之地,只是不是一个同等重要的地方。
  • @Chris 你是对的还是 Josh Bloch 在这里? stackoverflow.com/a/5080547/632951
  • 想想hibernate有一个方法:Session.get(Serializable id)。使用标记接口,您可以指定标识符必须是可序列化的。如果我们改用注解,那么当您执行以下操作时,您将不再能够获得编译时错误:session.get(new Object())。相反,我们必须在运行时检查注释并发出异常。
  • BTW 标记接口不能被注释完全替换,因为您可以确保参数具有标记接口,但没有注释,例如writeObject(Serializable s)这个对marker接口的检查不能用注解代替。
  • 根据这个逻辑(“没有行为的接口几乎不提供类型安全”),Set 接口也不应该存在。它没有提供任何超过Collection 的额外方法,仅指定合约。
【解决方案3】:

这样的标记接口在其他代码根据对象是否实现某个标记接口做出决定的情况下很有用。

在Serializable的情况下,将使用反射来序列化对象的字段。

现在首选注释,因为它们不会传播到子类。

见Marker interface pattern。

【讨论】:

  • 可序列化,不可序列化 :)
  • 是的,我搞砸了,我总是在接口名称前加上“I”:)
  • @Gregory Heresy,这是 Java!即使在 .NET 世界中,也应该忘记这个 COM(坏)约定!
  • Eclipse 不是 Java 代码的好例子。这可能是最糟糕的情况之一。
  • 主观和争论:p
【解决方案4】:

它表明类(以及所有非瞬态的字段)是序列化的候选对象。如果你正在构建一个依赖于序列化的框架,你当然可以这样编写一个方法:

public void registerObject(Serializable obj);

限制你准备接受的课程。

因为序列化对象需要保持跨系统的兼容性,所以序列化是明确的设计决策,因此需要使用标记接口来识别此类候选对象。

还有一个安全方面。您不想让所有内容都可序列化 - 否则您可能会通过序列化意外暴露(例如)密码或其他敏感数据。

【讨论】:

    【解决方案5】:

    它们被称为标记接口。顾名思义,它们标记某些对象可用于某些类型的操作。

    Serializable 表示该对象有资格进行 java 序列化,例如。

    已经讨论过它们是否不应该被注释代替,因为它们的功能非常相似。

    【讨论】:

      【解决方案6】:

      如果你实现了一个接口,那么instanceof 将是真的。如果你的接口没有什么要实现的,那么你可以使用它来标记一个带有元数据的类,就像 Java 1.5 及更高版本的注释一样,而不必强制实现者做任何特别的事情。

      【讨论】:

        【解决方案7】:

        您的推理是正确的,空接口不会影响程序的“标准”执行,该程序基于字段的检查/变异和方法的分派。

        但是,标记接口在与反射结合使用时很有用:库/方法检查(通过反射)一个对象,如果其类实现标记接口,则其工作方式不同。从 Java5 开始,几乎不需要标记接口 - 可以通过 Java 注释实现相同的“标记”功能 - (再次)它们的大部分效果将通过基于反射的代码来实现。

        【讨论】:

          【解决方案8】:

          主要目的是告诉编译器对实现了标记接口的类的对象区别对待。

          【讨论】:

          • 这是完全错误的。 Java 编译器或 JVM 对 Serializable 和其他标记接口没有什么特别的,但是使用它的 Java 库类需要识别 Serializable 对象,他们可能会考虑并以不同的方式处理这些对象,但编译器或 JVM 则不然。这是对标记接口的常见误解。
          【解决方案9】:

          仔细查看 Java 中的标记接口,例如Serializable、Clonnable 和 Remote 看起来它们用于向编译器或 JVM 指示某些内容。因此,如果 JVM 看到一个类是可序列化的,它会对它进行一些特殊的操作,类似地,如果 JVM 看到一个类是实现可克隆的,它会执行一些操作来支持克隆。 RMI 和远程接口也是如此。所以简而言之,Marker 接口向 Compiler 或 JVM 指示、信号或命令。

          阅读更多:http://javarevisited.blogspot.com/2012/01/what-is-marker-interfaces-in-java-and.html#ixzz2v6fIh1rw

          【讨论】:

          • 这是完全错误的。 Java 编译器或 JVM 对 Serializable 和其他标记接口没有什么特别的,但是使用它的 Java 库类需要识别 Serializable 对象,他们可能会考虑并以不同的方式处理这些对象,但编译器或 JVM 则不然。这是对标记接口的常见误解。
          猜你喜欢
          • 2012-07-13
          • 2011-05-25
          • 2011-05-21
          • 1970-01-01
          • 1970-01-01
          • 2011-02-25
          • 1970-01-01
          • 2017-06-01
          相关资源
          最近更新 更多