Design patterns 什么';Marker接口的好处是什么?

Design patterns 什么';Marker接口的好处是什么?,design-patterns,marker-interfaces,Design Patterns,Marker Interfaces,marker界面的想法或目的对我来说完全没有意义 在Java中搜索“可序列化类”时,我不可避免地想到了这个概念,“标记接口”。我理解为什么以及何时使用它——标记/标记类,使其具有特殊用途,如序列化 但这里最大的一点是,原因本身,我的意思是标记类的想法,表明我们将使用它进行某些用途,但没有任何方法,对我来说,这似乎是毫无意义的 如果我们想赋予一个类一些特殊的含义,以便它能够执行我们的目标任务,我坚信它应该包含为该任务编写的方法。如果它内部不包含任何内容,那么它与普通类的区别是什么?我甚至可以将“i

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

在Java中搜索“可序列化类”时,我不可避免地想到了这个概念,“标记接口”。我理解为什么以及何时使用它——标记/标记类,使其具有特殊用途,如序列化

但这里最大的一点是,原因本身,我的意思是标记类的想法,表明我们将使用它进行某些用途,但没有任何方法,对我来说,这似乎是毫无意义的

如果我们想赋予一个类一些特殊的含义,以便它能够执行我们的目标任务,我坚信它应该包含为该任务编写的方法。如果它内部不包含任何内容,那么它与普通类的区别是什么?我甚至可以将“implements Serializable”放在任何不打算序列化的类中


总而言之-标记接口有什么好处?

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

例如,正如您提到的,Serializable是一个没有任何函数的Marker接口的好例子。JVM为序列化过程标识实现可序列化的类及其对象


因此,如果我们想要识别对象类型来执行任何特定的操作。我们可以创建自己的标记接口并使用它。

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

例如,正如您提到的,Serializable是一个没有任何函数的Marker接口的好例子。JVM为序列化过程标识实现可序列化的类及其对象


因此,如果我们想要识别对象类型来执行任何特定的操作。我们可以创建自己的标记接口并使用它。

确实应该避免使用标记接口

有一些方法可以在没有标记接口的情况下完成与使用标记接口相同的事情,这些方法肯定是首选的,因为标记接口在某种程度上被视为一种代码气味

在C#中,可以使用可应用于类的属性。虽然执行安全强制转换相当快,但这些速度肯定较慢,但有一些方法可以通过基于输入类型的缓存来提高速度

我发现在许多情况下使用普通的
对象
,与期望使用标记接口相比,可能更灵活,因为这样会减少实现者的负担


确实不需要标记接口。

确实应该避免标记接口

有一些方法可以在没有标记接口的情况下完成与使用标记接口相同的事情,这些方法肯定是首选的,因为标记接口在某种程度上被视为一种代码气味

在C#中,可以使用可应用于类的属性。虽然执行安全强制转换相当快,但这些速度肯定较慢,但有一些方法可以通过基于输入类型的缓存来提高速度

我发现在许多情况下使用普通的
对象
,与期望使用标记接口相比,可能更灵活,因为这样会减少实现者的负担


实际上不需要标记接口。

在Java引入注释(在JDK 5中)之前,标记接口最初用于为类附加特殊意义。例如,该接口是在JDK1.1中创建的。随着注释的引入,如果需要标记一个类,并且不需要额外的方法,那么更好的方法是使用注释

例如,与其让类实现没有方法的
@Serializable
接口,更好的方法是创建一个注释
@Serializable
,并将该注释应用于类(请注意,
@Serializable
不是JDK中包含的真正注释)

有关如何创建和处理注释的更多信息,请参见(请原谅,我撰写了那篇文章;它包含了您需要了解的有关注释处理的信息,而不会因为直接在此处复制而弄乱此答案)


另一种方法是改变标记接口背后的思维过程,而不是处理类并根据它们的标记执行操作,将逻辑推送到类本身。例如,与查找具有
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);

在Java引入注释之前(在JDK5中),标记接口最初用于为类附加特殊意义。例如,该接口是在JDK1.1中创建的。随着注释的引入,如果需要标记一个类,并且不需要额外的方法,那么更好的方法是使用注释

例如,与其让类实现没有方法的
@Serializable
接口,更好的方法是创建一个注释
@Serializable
,并将该注释应用于类(请注意,
@Serializable
不是JDK中包含的真正注释)

有关如何创建和处理注释的更多信息,请参见(请原谅,我撰写了那篇文章;它包含了您需要了解的有关注释处理的信息,而不会因为直接在此处复制而弄乱此答案)


另一种方法是改变标记接口背后的思维过程,而不是处理类和执行动作
public class Foo implements Serializable {}

ObjectOutputStream os = // ... some output stream
Foo foo = new Foo();
foo.writeObject(os);