将TYPE注释传递给方法而不是标记接口

时间:2019-02-05 20:47:19

标签: java interface annotations

[答案编辑] :简短的答案是我要执行的操作是不可能的。我的问题有点误导。我了解到Marker Interface模式实际上就是我在问题中所说的“标记注释”(因为您创建的注释实际上是一个接口)。并且只能在运行时进行检查。因此,如果您希望对带有批注的编译时进行检查,那是不可能的。空接口是唯一的选择。检查答案以了解如何在运行时执行此操作。


我试图避免使用标记界面,而使用标记注释。基本上,我希望一堆带有此批注的类,并将这些类的实例传递给接受该 type 的方法。这是我的代码:

标记注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Message {
}

CLASS:

@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

我不确定自己在做什么,但是我读到可以用标记注释替换标记接口。在这种情况下不可能吗?

谢谢

2 个答案:

答案 0 :(得分:0)

marker interface pattern是一种向运行时可读的程序类型或对象中添加元数据的方法。

例如,参见此模式的休眠实现。 Their insert method接受普通的java.lang.Object,并且在该方法中使用来自各种注释的元数据。

因此,按照您的示例实现,我将采用类似的方式

public class DatabaseWriter {
    public void save(Object msg) {
        if (msg.getClass().isAnnotationPresent(Message.class)) { 
           //some code
        }
    }
}

答案 1 :(得分:0)

在您的示例中,MessageTypeAMessage在类层次结构中不相关。仅当表达式的类型是形式参数类型的子类型时,方法调用才合法。

建立子类型关系的一种方法是使用接口,如您已经提到的。

建立子类型关系的另一种方法是使用类型限定符(表示为类型注释)。

类型质量等级:

   @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是使您能够构建可强制使用正确的可插入类型检查器的工具。 (免责声明:我是该工具的维护者,但它是Amazon,Google,Uber等公司开发工具链的常规部分)。

您可以在几行代码中define your own type system。但是,仍然consider using Java subtypes rather than type qualifiers