Java中的标记接口?

Xav*_*uza 129 java design-patterns marker-interfaces

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

但最近我了解到它实际上与编译器或JVM无关.例如,在的情况下,Serializable接口的方法writeObject(Object)ObjectOutputStream不喜欢的东西instanceOf Serializable,以检测类实现是否Serializable与抛出NotSerializableException相应.一切都在代码中处理,这似乎是一个设计模式,所以我认为我们可以定义自己的标记接口.

现在我怀疑了:

  1. 上面提到的标记接口的定义在第一点是错误的吗?那么我们如何定义Marker接口呢?

  2. 而不是使用instanceOf运算符为什么不能使方法类似于writeObject(Serializable)有一个编译时类型检查而不是运行时?

  3. 注释如何比标记接口更好?

das*_*ght 114

  1. 上面提到的标记接口的定义在第一点是错误的吗? - 在(1)标记界面必须为空的部分中是正确的,并且(2)实施它意味着对实施类的某些特殊处理.不正确的部分是它意味着JVM或编译器会以不同的方式处理该类的对象:您正确地观察到它是Java类库的代码,将这些对象视为可克隆,可序列化等.它具有与编译器或JVM无关.
  2. 而不是使用instanceOf运算符,为什么方法不能像writeObject(Serializable)编译时类型检查那样 - 这样可以避免在需要"plain Object" 时使用标记接口的名称来污染代码.例如,如果您创建一个需要可序列化的类,并且具有对象成员,那么您将被迫Serializable在编译时进行转换或生成对象.这是不方便的,因为界面没有任何功能.
  3. 注释如何比标记接口更好? - 它们可以实现将类的元数据传递给其消费者的相同目的,而无需为其创建单独的类型.注释也更强大,让程序员将更复杂的信息传递给"消费"它的类.

  • 要记住的一件事是,在最初设计标准库几年后,注释被添加到语言中.如果注释从一开始就在语言中,那么Serializable本来就是一个接口是值得怀疑的,它可能就是一个注释. (15认同)
  • 我总是理解它的方式是Annotations是一种'Marker Interfaces 2.0':自Java 1.1起可存在Serializable,在1.5中添加了注释 (13认同)

h22*_*h22 22

不可能强制执行Serializable,writeObject因为非可序列化类的子类可以是可序列化的,但它们实例可以被上传回父类.因此,保持对不可序列化(如Object)的引用并不意味着引用的实例实际上不能被序列化.例如在

   Object x = "abc";
   if (x instanceof Serializable) {
   }
Run Code Online (Sandbox Code Playgroud)

parent class(Object)不可序列化,并且将使用其无参数构造函数进行初始化.由x,, 引用的值String是可序列化的,并且条件语句将运行.


Sha*_*khe 7

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

我们将具有可调式界面,将通过实施MobilePhone.java分类和多了一个类LandlinePhone.java里面做实现可移动的接口

我们的标记界面:

package com;

public interface Movable {

}
Run Code Online (Sandbox Code Playgroud)

LandLinePhone.javaMobilePhone.java

 package com;

 class LandLinePhone {
    // more code here
 }
 class MobilePhone implements Movable {
    // more code here
 }
Run Code Online (Sandbox Code Playgroud)

我们的自定义异常类: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
    }
Run Code Online (Sandbox Code Playgroud)

我们的测试课: 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");
}}
Run Code Online (Sandbox Code Playgroud)

现在当我们执行主类时:

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)
Run Code Online (Sandbox Code Playgroud)

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

这是instanceOfSerializableCloneable等进行操作员检查的方式


小智 6

Java中的标记接口是没有字段或方法的接口.更简单地说,Java中的空接口称为标记接口.的标记接口的例子是Serializable,CloneableRemote接口.这些用于向编译器或JVM指示一些信息.因此,如果JVM看到一个类Serializable,它可以对它进行一些特殊操作.同样,如果JVM看到某个类正在实现Cloneable,它可以执行一些操作来支持克隆.RMI和Remote接口也是如此.简而言之,标记接口指示编译器或JVM的信号或命令.

以上内容最初是一篇博客文章的副本,但对语法进行了轻微编辑.

  • 复制也没关系,但也请提及来源:http://javarevisited.blogspot.com/2012/01/what-is-marker-interfaces-in-java-and.html.如果你不复制粘贴拼写错误也会很好.:) (6认同)

Ser*_*sta 5

a /标记接口,顾名思义,仅存在于通知类的任何东西都在声明一个类。任何东西都可以是Serializable接口的JDK类,也可以是您为自定义类编写的任何类。

b /如果它是标记接口,则不应暗示存在任何方法-最好在接口中包含隐含方法。但你可以决定要设计它,只要你想,如果你知道为什么 需要它

c /空接口和不使用值或参数的注释之间几乎没有区别。但是区别在于:注释可以声明键/值的列表,这些键/值将在运行时访问。