На мой взгляд, интерфейсы служат для разделения абстракции и реализации. Собственно, зачем может понадобиться внутри интерфейса создавать класс, который будет обладать некоторой реализацией? Хотелось бы увидеть реальный пример использования внутренних классов в интерфейсах, чтобы понять, как такая особенность Java может быть использована.
Ответ
Пробежался структурным поиском по своему CLASSPATH и выловил следующие примеры:
Интерфейс как пространство имен
Самое частое - статический еnum, связнанный предметной областью с интерфейсом, объявленный внутри интерфейса. Интерфейс в данном случае играет роль пространства имен.
public interface Foo {
void foo(Bar bar);
static enum Bar { BAR1, BAR2, BAR3 }
}
Пример:
com.google.common.util.concurrent.Service
Похожий вариант - класс, описывающий value-тип, связанный с интерфейсом.
public interface Foo {
void foo(Bar bar);
static class Bar {
private final String id;
public Bar(Sting id) { this.id = id; }
public String getId() { return id; }
}
}
Пример:
org.hibernate.persister.entity.Queryable
io.undertow.security.api.AuthenticationMechanism
Несколько маленьких классов внутри интерфейса реализующих другой очень узкий интерфейс. Интерфейс используется только как пространство имен.
public interface Convertor {
String convert(Object arg);
}
public interface Convertors {
static class Convertor1 implements Convertor { String convert(Object arg) { /* ... */ }}
static class Convertor2 implements Convertor { String convert(Object arg) { /* ... */ }}
static class Convertor3 implements Convertor { String convert(Object arg) { /* ... */ }}
}
Пример:
org.hibernate.tuple.TimestampGenerators
Исключение, связанное с интерфейсом.
public interface Foo {
void foo() throws BarException;
static class BarException extends Exception {
// ...
}
}
Пример:
org.hibernate.boot.spi.InFlightMetadataCollector
Интерфейс объявляет внутри себя вспомогательные helper-классы с логикой, которые предлагает использовать реализациям.
Пример:
org.eclipse.jetty.io.ByteBufferPool
com.mysql.jdbc.SocketMetadata (5.1.39)
Интерфейс объявляет внутри себя готовую реализацию-заглушку.
public interface Foo {
Bar foo();
static class FooImpl implements Foo {
@Override
public void foo() { return null; }
}
}
Пример:
org.junit.Test
com.codahale.metrics.MetricRegistryListener
Интерфейс объявляет внутри себя Singleton, потому что "почему бы и нет": и так антипаттерн, так хоть локализовать его.
Пример:
org.asynchttpclient.channel.ChannelPoolPartitioning
Аннотация + обработчик
Статический класс реализующий некий интерфейс внутри интерфейса-аннотации описывающий логику этой аннотации.
Код, анализирующий аннотации скорее всего доберется до этого статического класса через рефлексию.
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo {
// annotation fields
static class FooHandler implements Handler
public interface Handler {
void handle(A a, Object arg);
}
Примеры:
javax.annotation.RegEx
javax.annotation.Nonnull
javax.annotation.Nonnegative
Комментариев нет:
Отправить комментарий