标记接口有啥好处?
Posted
技术标签:
【中文标题】标记接口有啥好处?【英文标题】:What's the good of Marker Interface?标记接口有什么好处? 【发布时间】:2019-11-13 16:06:45 【问题描述】:标记界面的想法或目的对我来说完全没有意义。
在 Java 中搜索“Serializable Class”时,我不可避免地想到了“标记接口”这个概念。我理解为什么以及何时使用它 - 标记/标记它用于特殊用途的类,例如序列化。
但这里最重要的一点是,原因本身,我的意思是标记类以表明我们将使用它进行某些用途但没有任何方法的想法,对我来说似乎是一派胡言。
如果我们想赋予一个类一些特殊的含义,以便它可以执行我们的目标工作,我坚信它应该包含为这些工作编写的方法。如果它里面什么都没有,那它和普通类有什么不同呢?我什至可以将“实现可序列化”放到任何不打算序列化的类中......
总结一下——标记界面的优点是什么?
【问题讨论】:
【参考方案1】:确实应该避免使用标记界面。
有一些方法可以在没有标记接口的情况下完成与使用标记接口相同的事情,并且这些方法绝对应该是首选,因为标记接口被认为有点代码味道。
在 C# 中,可以使用可应用于类的属性。尽管安全转换相当快,但它们肯定会更慢,但有一些方法可以通过基于输入类型的缓存来提高速度。
我发现在许多情况下使用普通的object
,而不是期待一个标记接口,可能更灵活,因为它给实施者带来更少的负担。
确实不需要标记界面。
【讨论】:
【参考方案2】:标记接口最初用于在 Java 引入注解之前(在 JDK 5 中)为类附加特殊含义。例如,Serializable
接口是在 JDK 1.1 中创建的。随着注解的引入,一个更好的方法——如果一个类需要被标记并且不需要额外的方法——是使用注解。
例如,与其让一个类实现没有方法的Serializable
接口,更好的方法是创建一个注解@Serializable
,并将该注解应用于一个类(注意@Serializable
不是 JDK中包含的真正注释)。
@Serializable
public class Foo
有关如何创建和处理注释的更多信息,请参阅Creating Annotations in Java(请原谅我撰写了那篇文章;它包含了您需要了解的有关注释处理的信息,而不会直接在此处复制此答案而造成混乱)。
另一种方法是改变标记界面背后的思维过程,而不是处理类并根据它们的标记执行操作,而是将逻辑推送到类本身。例如,与其查找带有Serializable
的类然后执行逻辑,不如将逻辑直接移动到Serializable
接口,允许客户端直接在对象上调用序列化逻辑。例如:
public interface Serializable
public default void writeObject(ObjectOutputStream out) throws IOException
// ... default logic ...
public default void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
// ... default logic ...
public default void readObjectNoData() throws ObjectStreamException
// ... default logic ...
那么可以直接序列化一个可序列化的对象:
public class Foo implements Serializable
ObjectOutputStream os = // ... some output stream
Foo foo = new Foo();
foo.writeObject(os);
【讨论】:
【参考方案3】:标记接口用于向类添加对未通过重写方法实现的功能的支持。
例如,当您声明一个类实现 Serializable
或 Cloneable
时,您允许将其传递给需要这些类型的方法,并承诺它通过 Liskov Substitution 遵守这些类型的约定原理:https://en.wikipedia.org/wiki/Liskov_substitution_principle
接口的隐含契约不仅仅是它让您覆盖的方法。
标记接口非常少见,因为对于使用接口方法实现接口所需的功能来说,它几乎总是更好。有时,就像Serializable
和Cloneable
的情况一样,但由于某种原因它不符合这种模式。在这些情况下使用标记接口,因为接口的其他功能仍然有效。
【讨论】:
【参考方案4】:标记接口仅用于类型识别。除此之外,Marker Interface 没有特定用途。
例如,正如您提到的,Serializable 是没有任何功能的 Marker 接口的一个很好的例子。实现 Serializable 的类及其对象由 JVM 识别进行序列化处理。
所以如果我们要识别 Object 类型来做任何特定的操作。我们可以创建自己的 Marker 接口并使用它。
【讨论】:
About Marker Interface 参考这个@rhee以上是关于标记接口有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章