Xav*_*uza 129 java design-patterns marker-interfaces
我被告知Java中的Marker接口是一个空接口,用于向编译器或JVM发出信号,表明必须以特殊方式处理实现此接口的类的对象,如序列化,克隆等.
但最近我了解到它实际上与编译器或JVM无关.例如,在的情况下,Serializable接口的方法writeObject(Object)的ObjectOutputStream不喜欢的东西instanceOf Serializable,以检测类实现是否Serializable与抛出NotSerializableException相应.一切都在代码中处理,这似乎是一个设计模式,所以我认为我们可以定义自己的标记接口.
现在我怀疑了:
上面提到的标记接口的定义在第一点是错误的吗?那么我们如何定义Marker接口呢?
而不是使用instanceOf运算符为什么不能使方法类似于writeObject(Serializable)有一个编译时类型检查而不是运行时?
注释如何比标记接口更好?
das*_*ght 114
writeObject(Serializable)编译时类型检查那样 - 这样可以避免在需要"plain Object" 时使用标记接口的名称来污染代码.例如,如果您创建一个需要可序列化的类,并且具有对象成员,那么您将被迫Serializable在编译时进行转换或生成对象.这是不方便的,因为界面没有任何功能.h22*_*h22 22
不可能强制执行Serializable,writeObject因为非可序列化类的子类可以是可序列化的,但它们实例可以被上传回父类.因此,保持对不可序列化(如Object)的引用并不意味着引用的实例实际上不能被序列化.例如在
Object x = "abc";
if (x instanceof Serializable) {
}
Run Code Online (Sandbox Code Playgroud)
parent class(Object)不可序列化,并且将使用其无参数构造函数进行初始化.由x,, 引用的值String是可序列化的,并且条件语句将运行.
我做了一个简单的演示来解决疑问 1 和 2:
我们将具有可调式界面,将通过实施MobilePhone.java分类和多了一个类LandlinePhone.java里面做不实现可移动的接口
我们的标记界面:
package com;
public interface Movable {
}
Run Code Online (Sandbox Code Playgroud)
LandLinePhone.java 和 MobilePhone.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将通过测试,否则将显示错误消息。
这是instanceOf对Serializable、Cloneable等进行操作员检查的方式
小智 6
Java中的标记接口是没有字段或方法的接口.更简单地说,Java中的空接口称为标记接口.的标记接口的例子是
Serializable,Cloneable与Remote接口.这些用于向编译器或JVM指示一些信息.因此,如果JVM看到一个类Serializable,它可以对它进行一些特殊操作.同样,如果JVM看到某个类正在实现Cloneable,它可以执行一些操作来支持克隆.RMI和Remote接口也是如此.简而言之,标记接口指示编译器或JVM的信号或命令.
以上内容最初是一篇博客文章的副本,但对语法进行了轻微编辑.
a /标记接口,顾名思义,仅存在于通知类的任何东西都在声明一个类。任何东西都可以是Serializable接口的JDK类,也可以是您为自定义类编写的任何类。
b /如果它是标记接口,则不应暗示存在任何方法-最好在接口中包含隐含方法。但你可以决定要设计它,只要你想,如果你知道为什么 你需要它
c /空接口和不使用值或参数的注释之间几乎没有区别。但是区别在于:注释可以声明键/值的列表,这些键/值将在运行时访问。