[答案]编辑]:简单的答案是什么,我希望做的是不可能的。我的问题是有点误导。我了解到,Marker Interface模式实际上是我称之为有标记注释在我的问题(因为你正在创建的注释实际上是一个接口)。并就检查只能在运行时进行。所以,如果你正在寻找让与注释的编译时检查,以及它是不可能的。空接口是唯一的选择。检查答案,看看如何在运行时做到这一点。
我试图避免使用有利于显着的注释标记接口。基本上,我想了一堆类打上这个注解,并通过这些类的实例来接受这种类型的方法。这里是我的代码:
标记注释:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Message {
}
类:
@Message
public class MessageTypeA {
}
方法:
public class DatabaseWriter {
public void save(Message msg) {
//some code
}
}
调用代码:
MessageTypeA msgA = new MessageTypeA();
DatabaseWriter writer = new DatabaseWriter();
writer.save(msgA);
但是我得到Error:(78, 23) java: incompatible types: MessageTypeA cannot be converted to Message
我不知道我在做什么是可能的,但我读的标记接口可与标记注释来代替。它是不可能在这种情况下?
谢谢
该marker interface pattern是添加到您的程序类型的对象元数据是在运行时可读的方式。
见例如Hibernate实现这种模式的。 Their insert
method接受一个普通java.lang.Object
,并且是其中使用从各种注释的元数据的方法的内部。
所以,下面的示例实现,我会像这样的东西去
public class DatabaseWriter {
public void save(Object msg) {
if (msg.getClass().isAnnotationPresent(Message.class)) {
//some code
}
}
}
在你的榜样,MessageTypeA
和Message
都在类层次结构无关。一个方法调用是合法的只有表达式的类型是形式参数的类型的子类型。
建立了子类型关系的一种方法是用一个接口,因为你已经注意到。
建立了子类型关系的另一种方法是用类型限定符(表示为类型注释)。
类型修饰符层次结构:
@Message
|
@MessageTypeA
其中@MessageTypeA
是@Message
的一个子类型,并且@Message
意味着未知类型的消息。 @Message
是默认的,如果没有类型注释被写入。
图书馆
public class DatabaseWriter {
public void save(Object msg) {
// some code that can run on any old message
}
public void saveA(@MessageTypeA Object msg) {
// some code that is specific to MessageTypeA
}
}
客户
Object msg = ...;
@MessageTypeA Object msgA = ...;
DatabaseWriter writer = new DatabaseWriter();
writer.save(msg); // legal
writer.save(msgA); // legal
writer.saveA(msg); // compile-time error
writer.save(msgA); // legal
没有运行时开销或表示:执法是在编译时完成。
这使您能够构建可插拔类型跳棋强制实施正确的使用的工具是Checker Framework。 (免责声明:我是工具的维护者,但它是在亚马逊,谷歌,尤伯杯等的开发工具链的常规部分)
您可以在几行代码define your own type system。然而,仍然consider using Java subtypes rather than type qualifiers。