Я только что нашел статический вложенный интерфейс в нашей кодовой базе.
class Foo {
public static interface Bar {
/* snip */
}
/* snip */
}
Я никогда не видел этого раньше. Первоначальный разработчик недоступен. Поэтому я должен спросить так:
Какова семантика статического интерфейса? Что изменится, если я удалю static
? Зачем кому-то это делать?
Ответы:
Ключевое слово static в приведенном выше примере является избыточным (вложенный интерфейс автоматически становится «статическим») и может быть удалено без влияния на семантику; Я бы порекомендовал его удалить. То же самое касается «public» в интерфейсных методах и «public final» в интерфейсных полях - модификаторы являются избыточными и просто добавляют беспорядок в исходный код.
В любом случае, разработчик просто объявляет интерфейс с именем Foo.Bar. Дальнейшая связь с классом включения отсутствует, за исключением того, что код, который не может получить доступ к Foo, также не сможет получить доступ к Foo.Bar. (Из исходного кода - байт-код или отражение могут получить доступ к Foo.Bar, даже если Foo закрыт для пакета!)
Это приемлемый стиль для создания вложенного интерфейса таким образом, если вы ожидаете, что он будет использоваться только из внешнего класса, чтобы вы не создавали новое имя верхнего уровня. Например:
источник
На вопрос был получен ответ, но одна из веских причин использовать вложенный интерфейс - если его функция напрямую связана с классом, в котором он находится. Хороший пример этого - a
Listener
. Если у вас есть класс,Foo
и вы хотите, чтобы другие классы могли прослушивать события в нем, вы могли бы объявить интерфейс с именемFooListener
, что нормально, но, вероятно, было бы более понятно объявить вложенный интерфейс и реализовать эти другие классыFoo.Listener
( вложенный классFoo.Event
неплох с этим).источник
java.util.Map.Entry
(который является интерфейсом, вложенным в другой интерфейс).Map.Entry
) или классы также были в этом пакете. Я говорю это потому, что мне нравится, чтобы мои занятия были короткими и конкретными. Также читатель может увидеть, какие другие объекты связаны с классом, посмотрев на классы в пакете. Я бы, наверное, имел пакетjava.collections.map
для карт. Это о ОО и модульности.java.util
в нем слишком многоutil
это какcommon
- запах ИМОjava.util
конечно, слишком много в нем. Тем не менее, я не думаю, что разбивать его на такие мелкозернистые пакеты, как вы предлагаете, также идеально.java.util.MapEntry
вне его собственного пакета. Первый рефлекс: как интерфейс связан с этим классом? Я смотрю в класс. Если Javadoc не ссылается на этот интерфейс, я понятия не имею, как они связаны. Плюс люди не смотрят на импортную упаковку. У каждого свое мнение. Никто не прав, никто не ошибаетсяИнтерфейсы-члены неявно статичны. Модификатор static в вашем примере может быть удален без изменения семантики кода. См. Также спецификацию языка Java 8.5.1. Декларации типов статических членов
источник
Внутренний интерфейс должен быть статическим для доступа. Интерфейс связан не с экземплярами класса, а с самим классом, поэтому к нему можно получить доступ
Foo.Bar
следующим образом:В большинстве случаев это не отличается от статического внутреннего класса.
источник
The interface isn't associated with instances of the class, but with the class itself
более, я неОтвет Джесси близок, но я думаю, что есть лучший код, чтобы продемонстрировать, почему внутренний интерфейс может быть полезен. Посмотрите на код ниже, прежде чем читать дальше. Можете ли вы найти, почему внутренний интерфейс полезен? Ответ в том, что класс DoSomethingAlready может быть создан с любым классом, который реализует A и C; не только конкретный класс зоопарка. Конечно, это может быть достигнуто, даже если AC не является внутренним, но представьте, что объединяете более длинные имена (не только A и C) и делаете это для других комбинаций (скажем, A и B, C и B и т. Д.), И вы легко Посмотрите, как все выходит из-под контроля. Не говоря уже о том, что люди, проверяющие ваше дерево исходников, будут перегружены интерфейсами, которые имеют смысл только в одном классе.внутренний интерфейс позволяет создавать пользовательские типы и улучшает их инкапсуляцию .
источник
Zoo
действительно не реализует интерфейсAC
, поэтому случаиZoo
не могут быть переданы в конструктор ,DoSomethingAlready
который ожидаетAC
. Тот факт, чтоAC
расширяет оба,A
иC
, не означает, что классы реализуютA
иC
волшебным образом также реализуютAC
.Чтобы ответить на ваш вопрос очень прямо, посмотрите на Map.Entry.
Map.Entry
также это может быть полезно
Статическая Вложенная Inerfaces Запись в блоге
источник
Обычно я вижу статические внутренние классы. Статические внутренние классы не могут ссылаться на содержащие классы, в отличие от нестатических классов. Если вы не столкнетесь с какими-то коллизиями пакетов (там уже есть интерфейс под названием Bar в том же пакете, что и Foo), я думаю, я бы сделал это своим собственным файлом. Это также может быть дизайнерское решение для обеспечения логической связи между Foo и Bar. Возможно, автор предполагал, что Bar будет использоваться только с Foo (хотя статический внутренний интерфейс этого не навязывает, просто логическое соединение)
источник
Если вы замените класс Foo на интерфейс Foo, ключевое слово public в приведенном выше примере также будет избыточным, поскольку
источник
В 1998 году Филипп Вадлер предложил различие между статическими интерфейсами и нестатическими интерфейсами.
Например, он предложил решение проблемы выражения , которая заключается в несоответствии между выражением «сколько может выражаться ваш язык», с одной стороны, и выражением «термины, которые вы пытаетесь представить на своем языке», с другой стороны. ,
Пример различия между статическими и нестатическими вложенными интерфейсами можно увидеть в его примере кода :
Его предложение никогда не делалось в Java 1.5.0. Следовательно, все остальные ответы верны: нет никакой разницы для статических и нестатических вложенных интерфейсов.
источник
В Java статический интерфейс / класс позволяет использовать интерфейс / класс как класс верхнего уровня, то есть он может быть объявлен другими классами. Итак, вы можете сделать:
Без статики вышеприведенное не скомпилируется. Преимущество этого в том, что вам не нужен новый исходный файл только для объявления интерфейса. Он также визуально связывает интерфейс Bar с классом Foo, поскольку вы должны написать Foo.Bar, и подразумевает, что класс Foo делает что-то с экземплярами Foo.Bar.
Описание типов классов в Java .
источник
Статический означает, что любая часть класса пакета (проекта) может получить к нему доступ без использования указателя. Это может быть полезно или мешать в зависимости от ситуации.
Прекрасным примером использования "статических" методов является класс Math. Все методы в математике являются статическими. Это означает, что вам не нужно выходить из своего пути, создавать новый экземпляр, объявлять переменные и хранить их в еще большем количестве переменных, вы можете просто ввести свои данные и получить результат.
Статика не всегда так полезна. Например, если вы делаете сравнение случаев, вы можете хранить данные несколькими различными способами. Вы не можете создать три статических метода с одинаковыми сигнатурами. Вам нужно 3 разных экземпляра, не статичных, а затем вы можете сравнить их, потому что если они статические, данные не изменятся вместе с вводом.
Статические методы хороши для одноразовых возвратов и быстрых вычислений или легко получаемых данных.
источник