当前位置: 首页 > 知识库问答 >
问题:

Java 中的标记接口?

谭琛
2023-03-14

我被告知Java中的标记接口是一个空接口,用于向编译器或JVM发出信号,表明实现此接口的类的对象必须以特殊方式处理,如序列化、克隆等。

但是最近我了解到,它实际上与编译器或JVM无关。例如,在< code>Serializable接口的情况下,< code>ObjectOutputStream的方法< code>writeObject(Object)执行类似于< code > instance of Serializable 的操作,以检测该类是否实现了< code>Serializable

现在我的疑惑:

> < li>

上面第1点中提到的标记接口的定义是否错误?那么我们如何定义一个标记接口呢?

而不是使用 instanceOf 运算符,为什么该方法不能像 writeObject(可序列化)这样,以便进行编译时类型检查而不是运行时?

注释如何优于标记界面?

共有3个答案

白昊乾
2023-03-14

我做了一个简单的演示来解决疑问1和2:

我们将拥有可移动接口,该接口将由移动电话.java类和另外一类固定电话实现.java该类不实现可移动接口

我们的标记界面:

package com;

public interface Movable {

}

LandLinePhone.javaMobilePhone.java

 package com;

 class LandLinePhone {
    // more code here
 }
 class MobilePhone implements Movable {
    // more code here
 }

我们的自定义异常类:package.com;

public class NotMovableException extends Exception {

private static final long serialVersionUID = 1L;

    @Override
    public String getMessage() {
        return "this object is not movable";
    }
    // more code here
    }

我们的测试类:< code > testmarkerinterface . Java

package com;

public class TestMarkerInterface {

public static void main(String[] args) throws NotMovableException {
    MobilePhone mobilePhone = new MobilePhone();
    LandLinePhone landLinePhone = new LandLinePhone();

    TestMarkerInterface.goTravel(mobilePhone);
    TestMarkerInterface.goTravel(landLinePhone);
}

public static void goTravel(Object o) throws NotMovableException {
    if (!(o instanceof Movable)) {
        System.out.println("you cannot use :" + o.getClass().getName() + "   while travelling");
        throw new NotMovableException();
    }

    System.out.println("you can use :" + o.getClass().getName() + "   while travelling");
}}

现在,当我们执行main类时:

you can use :com.MobilePhone while travelling
you cannot use :com.LandLinePhone while travelling
Exception in thread "main" com.NotMovableException: this object is not movable
    at com.TestMarkerInterface.goTravel(TestMarkerInterface.java:22)
    at com.TestMarkerInterface.main(TestMarkerInterface.java:14)

因此,哪个类实现了标记接口Moable将通过测试,否则将显示错误消息。

这是对可序列化、可克隆等进行< code>instanceOf运算符检查的方式

戚均
2023-03-14

不可能在 writeObject 上强制实施可序列化,因为不可序列化类的子类可以序列化,但它们的实例可能会向上转换回父类。因此,持有对不可序列化的内容(如 Object)的引用并不意味着引用的实例不能真正序列化。例如在

   Object x = "abc";
   if (x instanceof Serializable) {
   }

父类(< code>Object)不可序列化,将使用其无参数构造函数进行初始化。由< code>x、< code>String引用的值是可序列化的,并且条件语句将运行。

金阳华
2023-03-14
  1. 上述第1点中提到的标记界面的定义是否错误?-正确的做法是:(1)标记接口必须为空,(2)实现它意味着对实现类进行某种特殊处理。不正确的部分是,这意味着JVM或编译器将以不同的方式对待该类的对象:您可以正确地观察到,是Java类库的代码将这些对象视为可克隆、可序列化等。它与编译器或JVM无关
  2. 而不是使用instanceOf操作符,为什么该方法不能像writeObject(Serializable)那样,以便进行编译时类型检查-这样可以避免在需要“纯对象”时用标记接口的名称污染代码。例如,如果您创建了一个需要可序列化的类,并且有对象成员,那么您将被迫在编译时执行强制转换或使对象serializable。这很不方便,因为该界面没有任何功能
  3. 注释如何优于标记界面?-它们允许您实现相同的目的,即将类的元数据传递给消费者,而无需为其创建单独的类型。注释也更强大,让程序员可以将更复杂的信息传递给“使用”它的类
 类似资料:
  • 问题内容: 标记接口是什么?它们的作用是什么? 问题答案: 因为有时候,想到类型的某些属性可以用作类型本身确实很有意义。如果我做这样的方法: …您真的不知道该如何保存。VM序列化?Bean属性序列化?一些自制的方案?而如果您这样写: …非常清楚(如果只有的设计师使用过这种可能性!)。有时,当您想向类型添加元数据时,可以使用注释,但是在这种情况下,我建议使用标记接口。

  • 问题内容: 当在标记界面中没有什么要实现的东西时,实现它有什么用? 问题答案: 在Java的早期版本中,标记接口是声明有关类的元数据的唯一方法。例如,可序列化标记接口使类的作者可以说他们的类在进行序列化和反序列化时将表现正确。 在现代Java中,标记接口没有位置。它们可以完全由Annotations代替,从而具有非常灵活的元数据功能。如果你具有有关类的信息,并且该信息永不更改,则注释是表示它的非常

  • 标记接口是一个没有任何成员的接口。可序列化就是一个例子。 我们可以定义自己的标记界面吗。如果是,我们如何定义它的功能。?

  • 问题内容: 有人可以解释一下Java中标记接口的约定吗? 例如:如果标记界面没有字段/方法,那么定义在哪里? 为什么每次使用时都应实施i / f ? 好吧,我的问题是,如果是类方法,为什么要实现i / f来覆盖。 有人可以详细说明一下Java的这种约定吗? 提前致谢 问题答案: 在所有类的扩展类中定义,但它是。这实际上是一个具体的方法实现,它对对象进行逐字段克隆,但前提是您已实现接口以表明允许这样

  • 有人可以解释一下 java 中标记接口的契约吗? 例如:如果是一个没有字段/方法的标记接口,那么在哪里定义? 为什么每当使用 时,我们都应该实现的 i/f? 好吧,我的问题是,如果是 class的一种方法,为什么要实现 i / f来覆盖 有人能详细说明一下java的这个惯例吗? 提前致谢

  • 问题内容: 在阅读有关标记接口的信息时,我偶然发现了以下站点:项目37:使用标记接口定义类型 在这里,根据Joshua Bloch的说法,标记接口比标记注释有两个优点。 1. 标记接口定义了一种由标记的类的实例实现的类型。标记注释没有。这种类型的存在使您可以在编译时捕获错误,而如果使用标记注释,则这些错误在运行时才捕获。 2. 标记接口相对于标记注释的另一个优点是可以更精确地定位它们。如果使用ta