Передача аннотаций TYPE в методы вместо интерфейсов маркеров - PullRequest
0 голосов
/ 05 февраля 2019

[РЕДАКТИРОВАТЬ ОТВЕТ]: Короткий ответ: то, что я хочу сделать, невозможно.Мой вопрос немного вводит в заблуждение.Я узнал, что шаблон 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

IЯ не уверен, что то, что я делаю, возможно, но я читал, что интерфейсы маркеров можно заменить аннотациями маркеров.Разве это не возможно в этом случае?

Спасибо

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

В вашем примере 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
    }
}

CLIENT

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 и т. Д.)

Вы можете определить свою собственную систему типов в несколько строк кода.Тем не менее, все же рассмотрите возможность использования подтипов Java, а не квалификаторов типов .

0 голосов
/ 06 февраля 2019

Шаблон интерфейса маркера - это способ добавления метаданных к типам программ или объектам, которые доступны для чтения во время выполнения.

См., Например, реализацию этого шаблона в режиме гибернации. Их insert метод принимает простой java.lang.Object и находится внутри этого метода, где используются метаданные из различных аннотаций.

Итак, следуя вашей примерной реализации, я бы пошелс чем-то вроде этого

public class DatabaseWriter {
    public void save(Object msg) {
        if (msg.getClass().isAnnotationPresent(Message.class)) { 
           //some code
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...