Какая польза от маркерных интерфейсов в Java?

Когда нечего реализовывать в интерфейсах маркеров, таких как Serializable ., какая польза от его реализации?

10 ответов

Решение

В более ранних версиях Java интерфейс Marker Interfaces был единственным способом объявления метаданных о классе. Например, интерфейс Serializable Marker Interface позволяет автору класса сказать, что его класс будет вести себя правильно при сериализации и десериализации.

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

Джошуа Блох: Эффективное Java, 2-е издание, стр. 179

Правило 37: Используйте маркерные интерфейсы для определения типов

... Возможно, вы слышали, что аннотации маркеров (пункт 35) делают интерфейсы маркеров устаревшими. Это утверждение неверно. Интерфейсы маркеров имеют два преимущества перед аннотациями маркеров. Прежде всего, маркерные интерфейсы определяют тип, который реализуется экземплярами помеченного класса; маркерных аннотаций нет. Существование этого типа позволяет вам отлавливать ошибки во время компиляции, которые вы не могли отловить до времени выполнения, если использовали аннотацию маркера....

Лично я думаю, что я преклоняюсь перед превосходными знаниями Джошуа по этому вопросу.

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

В случае SerializableОтражение будет использоваться для сериализации полей объектов.

Теперь аннотации предпочтительнее, так как они не распространяются на подклассы.

См. Шаблон интерфейса Маркер.

Они называются маркерными интерфейсами. И как следует из названия, они отмечают, что некоторый объект доступен для определенного вида операций.

Serializable означает, что объект пригоден для сериализации Java, например.

Обсуждается, не следует ли их заменять аннотациями, поскольку их функции очень похожи.

Это указывает на то, что класс (и, следовательно, все поля, которые не являются переходными) являются кандидатами для сериализации. И если вы создаете фреймворк, зависящий от сериализации, вы, конечно, можете написать метод так:

public void registerObject(Serializable obj);

ограничить классы, которые вы готовы принять.

Поскольку сериализованный объект должен сохранять совместимость между системами, сериализация является явным решением проекта и, следовательно, требует использования интерфейса маркера для идентификации таких кандидатов.

Там также аспект безопасности. Вы не хотите делать все сериализуемым - иначе вы можете случайно раскрыть (скажем) пароли или другие конфиденциальные данные через сериализацию.

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

Вы правы в том, что пустой интерфейс не влияет на "стандартное" выполнение программы, которое основано на проверке / мутации полей и диспетчеризации методов.

Однако интерфейс маркера полезен, когда используется в сочетании с отражением: библиотека / метод проверяет (через отражение) объект и работает иначе, если его класс реализует интерфейс маркера. Начиная с Java5 очень мало необходимости в маркерных интерфейсах - такая же возможность "маркировки" может быть достигнута с помощью аннотаций Java - что (опять же) большая часть их эффекта будет достигаться с помощью основанного на отражении кода.

В основном мы видим использование маркерных интерфейсов в сценариях, где мы хотим проверить, имеет ли объект класса разрешение. Мы проверяем наличие разрешения с помощьюinstanceOf.

      public interface Herbivorous {
}
public interface Carnivorous {
}
public class Cow implements Herbivorous {
    String howMuchGrassConsumed() {
        return "2";
    };
}
public class Lion implements Carnivorous {
    String howManyCowsConsumed() {
        return "2";
    }
}
public class Jungle{
    public static void main(String[] args) {
        Cow cow = new Cow();
        Lion lion = new Lion();
        if(cow instanceof Herbivorous){
            System.out.println("Cow ate so much gress:"+cow.howMuchGrassConsumed());
        }else if(lion instanceof Carnivorous){
            System.out.println("Lion ate so many cows:"+lion.howManyCowsConsumed(););
        }else{
            System.out.println("That's an alien");
        }
    }
}

Внимательно изучая маркерный интерфейс в Java, например, Serializable, Clonnable и Remote, кажется, что они используются для указания чего-то компилятору или JVM. Поэтому, если JVM видит, что класс является сериализуемым, он выполняет над ним какую-то специальную операцию, аналогичным образом, если JVM видит, что один класс реализует Clonnable, он выполняет некоторую операцию для поддержки клонирования. То же самое верно для RMI и удаленного интерфейса. Таким образом, вкратце интерфейс Marker указывает на сигнал или команду для компилятора или JVM.

Узнайте больше: http://javarevisited.blogspot.com/2012/01/what-is-marker-interfaces-in-java-and.html

Основная цель - сообщить компилятору, что он по-разному относится к объекту класса, в котором реализован интерфейс маркера.

Другие вопросы по тегам