首页 > 解决方案 > 标记接口有什么好处?

问题描述

标记界面的想法或目的对我来说完全没有意义。

在 Java 中搜索“Serializable Class”时,我不可避免地想到了“Marker Interface”这个概念。我理解为什么以及何时使用它 - 标记/标记它用于特殊用途的类,例如序列化。

但这里最重要的一点是,原因本身,我的意思是标记类以表明我们将使用它进行某些用途但没有任何方法的想法,对我来说似乎是一派胡言。

如果我们想赋予一个类一些特殊的含义,以便它可以执行我们想要的工作,我坚信它应该包含为这些工作编写的方法。如果它里面什么都没有,那它和普通类有什么不同呢?我什至可以将“实现可序列化”放到任何不打算序列化的类中。

总结一下——标记界面有什么好处?

标签: design-patternsmarker-interfaces

解决方案


在 Java 引入注解(在 JDK 5 中)之前,标记接口最初用于为类附加特殊含义。例如,Serializable接口是在 JDK 1.1 中创建的。随着注解的引入,一个更好的方法——如果一个类需要被标记并且不需要额外的方法——是使用注解。

例如,与其让一个类实现Serializable没有方法的接口,更好的方法是创建一个注解,@Serializable然后将该注解应用到一个类(注意这@Serializable不是JDK包含的真正注解)。

@Serializable
public class Foo {}

有关如何创建和处理注释的更多信息,请参阅在 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);

推荐阅读