java中标记接口的意义何在?为啥没有它们我们就不能继续?

Posted

技术标签:

【中文标题】java中标记接口的意义何在?为啥没有它们我们就不能继续?【英文标题】:What is the point of marker interface in java and why can't we go on without them?java中标记接口的意义何在?为什么没有它们我们就不能继续? 【发布时间】:2020-02-24 09:24:05 【问题描述】:

我阅读了有关标记接口的内容,并且对如何在代码中使用它们有了一些了解,但我不明白为什么我们需要它们以及引入这个概念的原因是什么。

我在互联网上搜索,所有答案都类似于“它们向 JVM 提供一些基本信息,以便 JVM 可以执行一些有用的操作”,但问题是为什么 JVM 需要知道这一点以及可能的操作JVM必须执行吗?为什么我不能只克隆对象而不从 Clonable 扩展类?为什么我不能在不从 Serializable 扩展的情况下序列化类对象?

标记界面没有多大意义,在我看来显然不是一个好的设计。没有任何方法的接口???有什么意义?

现在显然这里要使用注释而不是标记接口,但问题仍然是为什么 JVM 需要知道?

【问题讨论】:

“标记”接口的重点是“标记”类。例如,一个没有直接或间接实现 Serializable 的类就不能被序列化。 “......为什么我们不能没有他们继续前进?”我们可以,我们可以。在某些情况下,为了保持向后兼容性,仍然需要旧的,但没有理由创建新的。 “......没有多大意义......”实际上,一旦你明白了这个概念,他们就会这样做。 "为什么我不能只克隆对象而不从 Clonable 扩展类?"如果语言是这样设计的,你本可以做到的。但是克隆文件句柄意味着什么?还是单身?有些东西应该克隆,有些则不;如果不告诉 JVM,没有明显的方法可以确定。 @Stultuske 是的,如果你这样说确实有些道理。 @AndyTurner 我明白你的意思 【参考方案1】:

您清楚地了解标记接口的作用。你自己也是这么说的!

那么为什么我们还需要它们呢?

在某种意义上,我们不需要它们。您可以使用标记接口表达的任何内容都可以使用注释来表达。毫无疑问,注释是解决问题的一种更简洁的方法。

我们(仍然)拥有标记界面的根本原因是历史

Java 注释在 Java 5.0 中被添加到 Java 语言中。在此之前,标记界面是可用的最佳解决方案。

从类中删除标记接口会破坏二进制兼容性。

有少量 Java SE 标记接口早于 Java 5.0,并广泛用于用户代码。想到的两个是SerializableCloneable

不管我们喜欢与否,Java 都有标记接口,而且这不太可能改变。


标记界面没有多大意义,在我看来显然不是一个好的设计。

嗯,是的。从 2019 年的角度来看,确实如此。

从 1997 年的角度来看,当时 Java 还是新的,而 C# 还需要 5 年的时间,唯一带有注释之类的主流 (-ish) 语言是 LISP 版本。

现在我很确定,Java 1.0 时代的 Java 类库的设计者已经意识到标记接口是一个有缺陷的想法。但他们别无选择。它使用了标记接口,或者将一些漂亮的 Java 基础 API 的设计和实现推迟了 5 年或更长时间。

在企业计算领域,您需要做出妥协才能完成工作。

【讨论】:

还有标记注释为@Configurationzetcode.com/spring/configuration @user7294900 - 是的......但是所有注释在某种意义上都是标记。这不是问题,因为注释就是这样设计的。【参考方案2】:

您不需要实现 Serializable 来进行序列化,或者 Cloneable 来进行克隆。这些接口的重点在于 Java 内置了用于克隆和序列化的机制,如果您希望使用这些内置机制,您只需要实现这些接口。

因此,只需实现 Serializable,您就可以自动将该类与 ObjectInputStream 和 ObjectOutputStream 一起使用,而无需任何额外代码。

另一方面,我觉得可克隆几乎没用。通常,您只需实现 Cloneable 并覆盖 Object.clone 并将其公开,您就可以立即进行克隆。但据说它已损坏,您最好编写自己的克隆逻辑,例如使用复制构造函数。

【讨论】:

【参考方案3】:

任何类都可以在不添加任何额外方法/字段/开销的情况下实现它的要点

您只需标记类,它就可以使用/序列化了

即使在引入注解的 Java 5.0 之后,

还有标记注释为@Configuration

@Configuration 注解用于基于 Spring 注解的配置。 @Configuration 是一个标记注解,它表明一个类声明了一个或多个@Bean 方法,并且可以由 Spring 容器处理以在运行时为这些 bean 生成 bean 定义和服务请求

【讨论】:

嗨,这就是问题,就像我说的,在互联网上人们说我们“标记”它并使用它,这没关系,但为什么要为 JVM 标记它。当我们标记它时,JVM会做什么。如果您知道我的意思,我正在寻找更多“幕后”的理由。一定是有原因的,但我想不通 @UzairAbid JVM 将如何识别特定的类?通过字段/类名/父类/...不太理想/可扩展的选项,您能否建议 JVM 应如何查找类的其他方式?【参考方案4】:

我可以回答你的部分问题 - java中标记接口的意义是什么?

通过引入注解,Java 为我们提供了一种替代方法,可以实现与标记接口相同的结果。此外,像标记接口一样,我们可以将注释应用于任何类,我们可以将它们用作指示符来执行某些操作。

那么关键的区别是什么?

与注解不同,接口允许我们利用多态性。因此,我们可以向标记界面添加额外的限制。

例如,让我们添加一个限制,即只能从数据库中删除 Shape 类型:

public interface Shape 
    double getArea();
    double getCircumference();

在这种情况下,我们的标记界面,我们称之为 DeletableShape,将如下所示:

public interface DeletableShape extends Shape 

那么我们的类就会实现标记接口:

public class Rectangle implements DeletableShape 
    // implementation details

因此,所有DeletableShape 实现也是Shape 实现。显然,我们不能使用注释来做到这一点

但是,每个设计决策都需要权衡取舍,并且 多态性可以用作针对标记接口的反驳在我们的示例中,每个扩展 Rectangle 的类都会自动实现 DeletableShape。


这可能无法提供您想要的确切答案。但可以部分帮助您。

来源:baeldung.com

【讨论】:

以上是关于java中标记接口的意义何在?为啥没有它们我们就不能继续?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们要实现标记接口,即使它们不包含任何方法? [复制]

#pragma 标记的意义​​是啥?为啥我们需要#pragma 标记?

spring 为啥要先写接口,再写实现类?

标记接口有啥好处?

Java 中菱形运算符 (<>) 的意义何在?

Java中的自定义标记接口