Java中标记接口的用途是什么?

Gur*_*lki 51 java annotations marker-interfaces

什么都没有在Serializable等标记接口中实现..实施它有什么用?

T C*_*T C 86

Joshua Bloch:Effective Java 2nd Edition,第179页

第37项:使用标记界面定义类型

...你可能会听到它说标记注释(第35项)使标记接口过时.这个断言是不正确的.标记接口与标记注释相比具有两个优点.首先,标记接口定义由标记类的实例实现的类型; 标记注释没有.这种类型的存在允许您在编译时捕获错误,如果您使用标记注释,则在运行时无法捕获这些错误....

我个人认为我会向约书亚在这个问题上的优秀知识屈服.

  • 实际上,甚至"Serializable"也可以看作是一种类型.考虑以下方法签名:public void serialize(Serializable objectToSerialize); 在这种情况下,在编译时很清楚只有可序列化的对象可以传递给"序列化",这对于注释是不可能的. (4认同)
  • 是的...非常好:) (2认同)

Chr*_*man 61

在早期版本的Java中,标记接口是声明类的元数据的唯一方法.例如,Serializable Marker Interface允许类的作者说序列化和反序列化时它们的类将正常运行.

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

  • 我真的很喜欢注释,但在这种情况下,它们的缺点是检查要复杂一些(与使用instanceof相比).它们也没有很好地集成在javadoc中(快速查看实现<marker interface>的方法是查看它并查看实现类列表).所以我会说他们仍然有一个地方,而不是一个同样重要的地方. (18认同)
  • @Chris你是对的还是Josh Bloch就在这儿?http://stackoverflow.com/a/5080547/632951 (12认同)
  • 想想hibernate有一个方法:Session.get(Serializable id).使用标记接口,您可以指定标识符必须是可序列化的.如果我们要使用注释,那么如果您执行类似这样的操作,则无法再获得编译时错误:session.get(new Object()).相反,我们必须在运行时检查注释并发出异常. (8认同)
  • BTW Marker接口不能完全被注释替换,因为您可以确保参数具有标记接口,但不能使用注释,例如`writeObject(Serializable s)`这种对标记接口的检查不能用注释替换. (2认同)
  • 根据这个逻辑("没有行为的接口几乎不提供类型安全性"),"Set"接口也不应该存在.它没有提供超过`Collection`的任何其他方法,只指定合同. (2认同)

Gre*_*osz 6

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

在这种情况下Serializable,反射将用于序列化对象的字段.

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

请参阅标记界面模式.

  • @Gregory Heresy,这是Java!即使在.NET世界中,也应该忘记这个COM(坏)惯例! (3认同)
  • 可序列化,而不是ISerializable :) (2认同)
  • Eclipse不是Java代码的一个很好的例子.这可能是最糟糕的事情之一. (2认同)
  • 主观的和议论的:p (2认同)

Bri*_*new 5

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

public void registerObject(Serializable obj);
Run Code Online (Sandbox Code Playgroud)

限制您准备接受的课程。

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

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


Boz*_*zho 5

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

Serializable例如,意味着该对象符合 java 序列化条件。

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