1

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

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

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

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

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

4

4 回答 4

0

在 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);
于 2019-07-03T12:56:46.143 回答
0

标记接口仅用于类型识别。除此之外,标记接口没有特定用途。

例如,正如您提到的 Serializable 是没有任何功能的 Marker 接口的一个很好的例子。实现 Serializable 的类及其对象由 JVM 识别以进行序列化过程。

所以如果我们要识别 Object 类型来做任何特定的操作。我们可以创建自己的 Marker 接口并使用它。

于 2019-07-03T02:33:15.820 回答
0

标记接口用于向类添加对通过覆盖方法实现的功能的支持。

例如,当您声明一个类实现SerializableCloneable时,您允许将其传递给需要这些类型的方法,并承诺它通过 Liskov 替换原则遵守这些类型的约定:https://en.wikipedia .org/wiki/Liskov_substitution_principle

接口的隐含契约不仅仅是它让你重写的方法。

标记接口非常少见,因为它几乎总是更好地满足使用接口方法实现接口所需的功能。有时,就像Serializableand的情况Cloneable一样,由于某种原因,它只是不适合该模式。在这些情况下使用标记接口,因为接口的其他功能仍然有效。

于 2019-07-05T13:14:36.143 回答
0

确实应该避免标记界面。

有一些方法可以在没有标记接口的情况下完成与使用标记接口相同的事情,并且这些方法绝对应该是首选,因为标记接口被认为有点代码味道。

在 C# 中,可以使用可应用于类的属性。尽管进行安全转换相当快,但它们肯定会更慢,但是有一些方法可以通过基于输入类型的缓存来提高速度。

我发现object在许多情况下使用普通的,而不是期待一个标记接口,可能更灵活,因为它给实现者带来了更少的负担。

确实不需要标记界面。

于 2019-07-03T04:20:49.857 回答