Ответ
Интерфейсы-маркеры (пустые интерфейсы, например, Serializable, Cloneable) устарели как концепция. Современные альтернативы более выразительны и функциональны:
1. Аннотации (Предпочтительный способ)
Аннотации несут семантическую информацию (метаданные) и могут иметь параметры.
// Вместо интерфейса-маркера Persistable
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Persistable {
String storage() default "default";
}
@Persistable(storage = "redis")
public class UserEntity { /* ... */ }
2. Интерфейсы с default-методами (начиная с Java 8)
Позволяют добавить поведение по умолчанию, сохраняя обратную совместимость.
// Вместо маркера Loggable
public interface Loggable {
// Метод по умолчанию, а не пустой интерфейс
default void log(String message) {
System.out.println("[" + getClass().getSimpleName() + "] " + message);
}
}
3. Функциональные интерфейсы (@FunctionalInterface)
Для обозначения интерфейсов с одним абстрактным методом (SAM). Аннотация @FunctionalInterface делает намерение компилятору и разработчику явным.
@FunctionalInterface // Явное указание назначения интерфейса
public interface Validator<T> {
boolean validate(T t);
// Можно добавлять default-методы
default Validator<T> and(Validator<T> other) {
return t -> validate(t) && other.validate(t);
}
}
4. Специализированные интерфейсы из java.util.function
Готовые функциональные интерфейсы для общих сценариев (Predicate, Function, Consumer).
Вывод: Аннотации и интерфейсы с поведением (default-методы) предоставляют более богатые и типобезопасные возможности для выражения намерений, чем пустые интерфейсы-маркеры.