Статьи

Есть ли лучший подход к маркеру?

С момента запуска Java 1.5 было много дискуссий и дискуссий о том, использовать ли интерфейс Marker в Java. Это связано с тем, что в Java 1.5 появились функции аннотаций, которые в значительной степени решают задачу интерфейса Marker. Эта статья будет охватывать интересный раздел этой дискуссии.

Определение:
Маркерный интерфейс в Java — это пустой интерфейс без каких-либо методов, полей или констант. Это иногда также называют интерфейсом тега.

Так почему используется интерфейс Marker?

Действительный вопрос !! Это не решает цель интерфейса, который определяет контракт с классами, которые реализуют этот интерфейс. Интерфейсы определяют методы без их реализации, поскольку сообщают дочерним классам, что необходимо сделать, но оставляют решение дочерним классам о том, как реализовать этот метод. Однако в случае интерфейса Marker нет членов.

Интерфейс маркера — это способ объявления метаданных о классе. Он сообщает JVM, что объекты классов, которые реализуют интерфейс маркера, должны обрабатываться с особой тщательностью по-другому. Некоторые из готовых интерфейсов Marker определены в Java API:
java.io.Serializable
java.lang.Cloneable
java.util.RandomAccess
java.util.EventListener
Мы также можем создать нашу собственную версию интерфейсов маркеров так же, как мы создаем другие интерфейсы.

Давайте углубимся в интерфейс Cloneable. Когда объект должен быть клонирован в Java, мы используем метод clone () объекта. Однако обратите внимание, что этот метод не является частью интерфейса Cloneable, т. Е. Когда ваш класс реализует интерфейс Cloneable по умолчанию, метод clone не будет реализован в отличие от любых других стандартных интерфейсов. Это можно сделать, когда мы явно определим его или вызовем метод клона объекта.
Следовательно, невозможно клонировать объект просто в силу того факта, что он реализует этот интерфейс. Даже если метод клона вызывается рефлексивно, нет никаких гарантий, что он будет успешным.

1
2
3
4
5
6
7
8
9
public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
}

Одним из ключевых моментов здесь является то, что при попытке клонировать объект с помощью метода clone () вы получите исключение CloneNotSupportedException, если вы не реализуете интерфейс Cloneable. JVM очень умная — не так ли?

Примечания к сведению:

Как упоминалось ранее, помимо использования встроенных интерфейсов маркеров, мы также можем создавать специфичные для приложений интерфейсы маркеров, так как это хороший способ пометить и логически классифицировать ваш фрагмент кода. Это в основном полезно при попытке создания фреймворка или разработке API.

Интересные моменты:

Runnable не является интерфейсом Marker. Хотя run — это специальная инструкция для JVM для запуска метода, но Runnable не является интерфейсом маркера, поскольку внутри него есть открытый метод void run ().

Проблема с интерфейсом маркера:

Основная проблема с интерфейсами маркеров заключается в том, что интерфейс определяет контракт для реализации классов, и этот контракт наследуется всеми подклассами. Это означает, что вы не можете отменить реализацию маркера. Если вы создаете подкласс, который вы не хотите сериализовать (возможно, потому что это зависит от переходного состояния), вы должны прибегнуть к явному выбрасыванию NotSerializableException .

Теперь вернемся к делу. Это лучший подход для использования аннотаций, чем интерфейс маркера?

Чтобы ответить на этот вопрос, давайте рассмотрим аннотации Java более подробно.

Определение:
Java-аннотации — это особая форма синтаксических метаданных (данных о данных), которая была представлена ​​в Java 1.5. Как и Java-классы, интерфейсы и аннотации могут быть использованы для нескольких элементов Java.

Интерфейс маркера против аннотации маркера

В отличие от Javadocs, аннотации более многофункциональны, что помогает в обработке во время выполнения. Аннотации используются в объявлении пакета или класса, объявлении метода, объявлении поля и объявлении переменной. Это сокращает усилия по написанию кода и позволяет разработчикам сосредоточиться на бизнес-логике с простотой разработки и, следовательно, повышает автоматизацию.

Аннотации отделены от стандартных элементов Java символом «@». Всякий раз, когда компилятор встречает эти аннотации с любым из элементов Java, он извлекает информацию из аннотации и генерирует код автоматически.

Использование аннотаций:

  • Передача информации в компилятор — используется для обнаружения ошибок или подавления предупреждений. Например, @SuppressWarnings, @deprecated
  • Обработка времени компиляции и времени развертывания. Некоторые инструменты могут обрабатывать информацию аннотаций для создания XML-файла кода и т. Д. В таких средах, как Spring, Hibernate, интенсивно используются аннотации.
  • Обработка во время выполнения — эти аннотации обрабатываются только во время выполнения.

По аналогии с интерфейсами маркеров у нас также есть аннотации маркеров. У аннотации маркера нет методов или элементов. Поведение такое же, как у интерфейсов Marker.

Например, @Override — это встроенный тип аннотации Java Marker, который может быть реализован в методе, чтобы указать компилятору компилятор, что метод переопределяет метод в суперклассе. Он не содержит никаких других программных элементов. Если вы используете эту аннотацию для метода, который не переопределяет метод суперкласса, компилятор выдаст ошибку компиляции, чтобы предупредить вас об этом факте. Этот тип аннотации защищает программиста от ошибки при переопределении метода, поскольку вполне возможно, что разработчики могут перегружать метод в суперклассе, а не переопределять его.

Кажется, аннотации — лучший выбор, чем интерфейс маркера, так как аннотации могут обеспечить тот же эффект.

  • Он может помечать переменные, методы и / или классы.
  • Он может пометить любой класс специально или с помощью наследования. Интерфейс маркера будет отмечать все подклассы отмеченного класса. Например, если мы должны пометить класс как не сериализуемый, мы должны специально пометить его как переходный. Это может быть спорным, так как аннотации не являются подклассифицированными, это может быть как преимуществом, так и недостатком. Аннотации не наследуются по умолчанию — isAnnotationPresent () сообщает вам, присутствует ли аннотация в этом конкретном классе, но нет, если она присутствует в суперклассе или суперинтерфейсе. Поэтому, если вы, как разработчик какой-либо специальной функциональности, которую аннотация предназначена для передачи, хотите, чтобы аннотация работала так, как если бы она была унаследована — вам нужно проверить isAnnotationPresent () не только для этого класса, но и для каждого суперкласса и каждого суперинтерфейса.
  • Вы можете добавить данные к отметке. Другими словами, аннотация, которая не является пустой, имеет значение, поскольку вы помечаете больше, чем просто текст.

Таким образом, каждый из них обладает определенными преимуществами и недостатками. Я лично считаю, что решение о том, использовать ли интерфейс маркера или аннотацию маркера, следует оставить разработчикам, поскольку они должны принять решение, учитывая ситуацию на месте, и судить о преимуществах и недостатках. их обоих и решите, что лучше всего подходит для этого требования.

Справка: есть ли лучший подход к маркеру? от нашего партнера JCG Майнака Госвами в блоге Idiotechie .