Почему все поля в интерфейсе неявно статичны и окончательны?

100

Я просто пытаюсь понять, почему все поля, определенные в интерфейсе, неявно staticи final. Идея сохранения полей staticимеет для меня смысл, поскольку у вас не может быть объектов интерфейса, но почему они final(неявно)?

Кто-нибудь знает, почему дизайнеры Java пошли на создание полей в интерфейсе staticи final?

пик
источник
На заметку для себя: он статичен, потому что поля интерфейса не станут частью объекта, который его реализует.
Raining

Ответы:

126

Интерфейс не может иметь поведение или состояние, потому что он предназначен для указания только контракта взаимодействия, без деталей реализации. «Отсутствие поведения» обеспечивается запретом тел методов / конструкторов или блоков инициализации статических / экземпляров. «Без состояния» принудительно разрешается только статические конечные поля. Следовательно, класс может иметь состояние (статическое состояние), но состояние экземпляра не определяется интерфейсом.

Кстати: константа в Java определяется статическим конечным полем (и по соглашению в имени используется UPPER_CASE_AND_UNDERSCORES).

Адриан Костер
источник
54
Необязательно, чтобы поля final были константами; это гарантировано только для примитивных типов. В общем, последнее ключевое слово просто означает, что место в памяти не изменится.
Pops
8
Я не сказал, что конечные поля являются константами, просто константы - это конечные поля. Обратите внимание, что в интерфейс разрешено помещать непримитивное статическое конечное поле. Несмотря на то, что содержимое этого поля может измениться, ссылка на него постоянна.
Адриан Костер
1
@AdriaanKoster Вы точно сказали, что последнее поле является константой: никакое состояние не применяется только при разрешении констант. - это предложение подразумевает, что все конечные поля постоянны. Вы можете продолжить спорить о словах, которые вы использовали, но очевидно, что ваше утверждение, по крайней мере, вводит в заблуждение.
Томаш Зато - Восстановите Монику
2
Должно быть, это из-за моего слабеющего интеллекта, но после шести лет рассмотрения этого ответа, который оказался моим лучшим ответом, я все еще не понимаю его замечания. Предложите другую формулировку, потому что я не вижу ничего плохого.
Адриан Костер,
Возможно, разработчики java намеревались сделать интерфейс без состояния, но им это не удалось, потому что поле экземпляра может быть модифицируемым классом. Вместо того, чтобы признать, что они потерпели неудачу, они предпочитают принудительно использовать поля экземпляра static final, что максимально близко к реальному (реальный - C / C ++), constнасколько это возможно в java. К сожалению, это подразумевается и может ввести в заблуждение неспециалиста. (Я понял, что это так, staticпотому что наблюдал непреднамеренное поведение. Я узнал, что они возникают finalтолько из этого ответа.)
not-a user
27

Причина существования final

Любые реализации могут изменять значение полей, если они не определены как окончательные. Тогда они станут частью реализации. Интерфейс - это чистая спецификация без какой-либо реализации.

Причина существования static

Если они статические, то они принадлежат интерфейсу, а не объекту или типу времени выполнения объекта.

Гурприт Сингх Сидхуу
источник
18

Здесь упущено несколько моментов:

Тот факт, что поля в интерфейсе являются неявно статическими final, не означает, что они должны быть константами времени компиляции или даже неизменными. Вы можете определить, например,

interface I {
  String TOKEN = SomeOtherClass.heavyComputation();
  JButton BAD_IDEA = new JButton("hello");
}

(Помните, что выполнение этого внутри определения аннотации может запутать javac , связанный с тем, что приведенное выше фактически компилируется в статический инициализатор.)

Кроме того, причина этого ограничения скорее стилистическая, чем техническая, и многие люди хотели бы, чтобы это было смягчено .

Джесси Глик
источник
9

Поля должны быть статическими, потому что они не могут быть абстрактными (как и методы). Поскольку они не могут быть абстрактными, разработчики не смогут логически предоставить различную реализацию полей.

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

Просто моя мысль.

NawaMan
источник
NawMan, ваше объяснение о том, что «поля должны быть статичными ...» не имеет особого смысла. Но вы были очень правы в том, что «Поля должны быть окончательными ...»
peakit
1
Я не думаю, что он прав относительно причины, по которой поля должны быть окончательными. Разрешить различным разработчикам изменять поле не составляет проблем, поскольку в противном случае наследование было бы проблематичным. Поля должны быть окончательными, как сказал Адриан, потому что интерфейс не имеет и не должен иметь состояния. Интерфейс с состоянием в основном должен быть абстрактным классом.
Axelle Ziegler
Если у вас есть public staticполе, которого нет final, findbugs пожалуется (правильно!).
Том Хотин - tackline
2

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

public interface iMine {
    String __ImplementationConstant();
    ...
}

public class AClass implements iMine {
    public String __ImplementationConstant(){
        return "AClass value for the Implementation Constant";
    }
    ...
}

public class BClass implements iMine {
    public String __ImplementationConstant(){
        return "BClass value for the Implementation Constant";
    }
    ...
}

Однако было бы проще, яснее и менее подверженным ошибочной реализации использовать этот синтаксис:

public interface iMine {
    String __ImplementationConstant;
    ...
}

public class AClass implements iMine {
    public static String __ImplementationConstant =
        "AClass value for the Implementation Constant";
    ...
}

public class BClass implements iMine {
    public static String __ImplementationConstant =
        "BClass value for the Implementation Constant";
    ...
}
Карл Клаппер
источник
Кажется, вы больше жалуетесь на то, что поля статичны, чем окончательны.
Daniel Yankowsky
0

Спецификация, контракты ... Машинная команда для доступа к полю использует адрес объекта плюс смещение поля. Поскольку классы могут реализовывать множество интерфейсов, невозможно сделать поле незавершенного интерфейса таким же смещением во всех классах, расширяющих этот интерфейс. Поэтому должен быть реализован другой механизм доступа к полю: два доступа к памяти (получение смещения поля, получение значения поля) вместо одного, плюс сохранение вида таблицы виртуальных полей (аналог таблицы виртуальных методов). Думаю, они просто не хотели усложнять jvm для функциональности, которую можно легко смоделировать с помощью существующих вещей (методов).

В scala у нас могут быть поля в интерфейсах, хотя внутри они реализованы, как я объяснил выше (как методы).

Ярослав
источник
-1

static:

Все , что (переменная или метод) , который находится staticв Java может служить Classname.variablenameили Classname.methodnameили непосредственно. Необязательно вызывать его только с использованием имени объекта.

В интерфейсе объекты не могут быть объявлены и staticпозволяет вызывать переменные только через имя класса без необходимости имени объекта.

final:

Это помогает поддерживать постоянное значение переменной, поскольку ее нельзя переопределить в ее подклассах.

Сабика
источник