Я изучаю Java и просто обнаружил, что интерфейс может иметь поля, которые являются публичными и конечными. Пока я их не видел. Каковы некоторые из вариантов использования этих констант интерфейса и могу ли я их увидеть в стандартной библиотеке Java?
Каково использование интерфейсных констант?
Ответ 1
Размещение статических членов в интерфейсе (и реализация этого интерфейса) плохой практики, и для него есть даже имя, константный интерфейс Antipattern, см. Эффективная Java, пункт 17:
Постоянный шаблон интерфейса плохо использует интерфейсы. То, что класс использует некоторые константы внутри, является деталью реализации. Внедрение постоянного интерфейса приводит к тому, что эта деталь реализации протекает в API-интерфейсе, экспортированном классом. Это не имеет никакого значения для пользователей класса, которые класс реализует постоянный интерфейс. На самом деле это может даже запутать их. Хуже того, он представляет собой обязательство: если в будущей версии класс модифицируется так, что ему больше не нужно использовать константы, он все равно должен реализовать интерфейс для обеспечения совместимости с двоичными файлами. Если нефинальный класс реализует константный интерфейс, все его подклассы будут иметь свои пространства имен, загрязненные константами в интерфейсе.
В библиотеках java-платформы существует несколько постоянных интерфейсов, таких как
java.io.ObjectStreamConstants
. Эти интерфейсы следует рассматривать как аномалии и не следует эмулировать.
Чтобы избежать некоторых ошибок постоянного интерфейса (потому что вы не можете помешать людям реализовать его), предпочтительным должен быть класс с частным конструктором (пример заимствован из Wikipedia):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
И чтобы получить доступ к константам, не имея возможности полностью их квалифицировать (т.е. без необходимости их префикса с именем класса), используйте статический импорт (начиная с Java 5):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
Ответ 2
"Постоянный шаблон интерфейса - плохое использование интерфейсов"
Кто бы ни придумал эту гипотезу, каким бы гуру он ни был, он придумал ее исходя из необходимости продолжать эффективно внедрять вредные привычки и практики. Гипотеза основана на продвижении обоснованности плохих привычек проектирования программного обеспечения.
Я написал опровержение ответа против этой гипотезы: каков наилучший способ реализации констант в Java? объясняя необоснованность этой гипотезы.
В течение 10 лет этот вопрос оставался открытым до тех пор, пока он не был закрыт в течение 2 часов после того, как я опубликовал свои доводы, оправдывающие эту гипотезу, и тем самым разоблачил нежелание обсуждать тех, кто придерживается этой ошибочной гипотезы.
Это то, что я высказал против гипотезы
-
Основой для сохранения этой гипотезы является необходимость в методах и ОГРАНИЧИТЕЛЬНЫХ правилах, чтобы справиться с последствиями вредных программных привычек и методологий.
-
Сторонники настроения "Постоянный шаблон интерфейса - это плохое использование интерфейсов" не могут представить никаких причин, кроме причин, вызванных необходимостью справиться с последствиями этих вредных привычек и практик.
-
Решить фундаментальную проблему.
-
А затем, почему бы не использовать в полной мере и не использовать все языковые возможности структуры языка Java для вашего удобства. Куртки не требуются. Зачем придумывать правила, чтобы забаррикадировать ваш неэффективный образ жизни, чтобы дискриминировать и обвинять в более эффективном образе жизни?
Основная проблема
это информационная организация. Информация, опосредующая процесс, и ее поведение следует сначала понять вместе с так называемыми бизнес-правилами, прежде чем разрабатывать или дополнять решения для процесса. Такой метод организации информации назывался нормализацией данных несколько десятилетий назад.
Тогда возможна только разработка решения, потому что согласование гранулярности и модульности компонентов решения с гранулярностью и модульностью компонентов информации является оптимальной стратегией.
Есть два или три существенных препятствия на пути организации информации.
-
Отсутствие восприятия для необходимости модели данных "нормализация".
-
Заявления Э. Ф. Кодда о нормализации данных ошибочны, неполноценны и неоднозначны.
-
Последнее увлечение, маскирующееся под проворную инженерию, - ошибочное представление о том, что не следует планировать и обуславливать организацию модулей впереди, потому что вы можете выполнять рефакторинг на ходу. В качестве оправдания используется рефакторинг и постоянные изменения без препятствий для будущих открытий. Существенные открытия поведения информации о процессах, таким образом, с помощью учетных приемов для отсрочки получения прибыли и сборов, в связи с чем необходимые знания и их обработка в настоящее время считаются ненужными.
Использование интерфейсных констант является хорошей практикой.
Не придумывайте правил и не выдвигайте против них фетву только потому, что вам нравятся ваши привычные хитроумные привычки.
Не запрещайте владение оружием по той причине, что есть люди, которые либо не знают, как обращаться с оружием, либо склонны злоупотреблять оружием.
Если правила, которые вы придумали, предназначены для программирования новичков, не умеющих профессионально программировать, и что вы относитесь к ним, то скажите так - не объявляйте вашу фетву применимой к правильно нормализованным моделям данных.
Глупое рассуждение - не было так, чтобы камбалы языка Java использовали интерфейсы?
Мне все равно, какие первоначальные намерения отцы-основатели имели для Конституции США. Меня не волнуют неписаные некодифицированные намерения. Меня волнует только то, что буквально кодифицировано в письменной Конституции, и как я могу использовать их для эффективного функционирования общества.
Меня волнует только то, что позволяют мне спецификации языка/платформы Java, и я намерен использовать их в полной мере, чтобы позволить мне эффективно и действенно выражать свои программные решения. Куртки не требуются.
Использование констант Enum на самом деле ужасная практика.
Это требует написания дополнительного кода для сопоставления параметра со значением. Тот факт, что основатели Java не предусмотрели сопоставление значения параметра без того, что вы написали, что код сопоставления демонстрирует, что константы Enum являются непреднамеренным использованием языка Java.
Тем более что вам не рекомендуется нормализовать и компоновать ваши параметры, может сложиться ложное впечатление, что параметры, смешанные в пакет Enum, принадлежат одному и тому же измерению.
Константы API Контракт
Не забывай это. Если вы разработали и нормализовали свою модель данных, и они содержат константы, то эти константы являются контрактами. Если вы не нормализовали свою модель данных, то вам следует придерживаться фатв, приведенных в том, как практиковать ограничительное кодирование, чтобы справиться с этой вредной привычкой.
Таким образом, интерфейсы являются идеальным способом реализации контракта констант.
Странное предположение - что делать, если интерфейс случайно реализован.
Ага. Любой может непреднамеренно реализовать любой интерфейс. Ничто не помешает таким непреднамеренным программистам.
Проектируйте и нормализуйте вашу модель данных от утечек
Не размещайте ограничительные декреты для защиты предполагаемых недобросовестных действий, которые вызывают утечку несокращенных/случайных параметров в API. Решите фундаментальную проблему, а не возлагайте вину на константы интерфейса.
Не использовать IDE - плохая практика
Нормально работающий и ЭФФЕКТИВНЫЙ программист не может доказать, как долго она может оставаться под водой, как далеко она может ходить при жаре или влажных грозах. Она должна использовать эффективный инструмент, такой как автомобиль или автобус или, по крайней мере, велосипед, чтобы ежедневно проехать 10 миль до работы.
Не устанавливайте ограничения на коллег-программистов только потому, что у вас есть эзотерическая аскетическая одержимость программированием без IDE.
Пара структур разработана, чтобы помочь программистам продолжать эффективно практиковать вредные привычки.
OSGI является такой основой. Так же как и указ против констант интерфейса.
Поэтому окончательный ответ...
Интерфейсные константы являются эффективным и действенным способом включения в контракт хорошо спроектированных и нормализованных компонентов модели данных.
Интерфейсные константы в соответствующем именованном частном интерфейсе, вложенном в файл класса, также являются хорошей практикой, чтобы группировать все ваши частные константы, а не разбрасывать их по всему файлу.
Ответ 3
Джошуа Блох, "Эффективное руководство по языку Java-программирования":
Постоянный шаблон интерфейса плохо использует интерфейсы. Который класс использует некоторые константы внутри - это деталь реализации. Внедрение постоянного интерфейса приводит к тому, что эта деталь реализации утечка в API, экспортированный классом. Это не имеет никакого значения для пользователей класса, который класс реализует постоянный интерфейс. В факт, это может даже запутать их. Хуже того, он представляет собой обязательство: если в будущей версии класс модифицируется так, что он больше не нужен для использования констант, он все равно должен реализовать интерфейс для обеспечения двоичная совместимость. Если нефинальный класс реализует константу интерфейса, все его подклассы будут иметь загрязненное пространство имен по константам в интерфейсе.
Ответ 4
Они полезны, если у вас есть общие константы, которые будут использоваться в классах, реализующих интерфейс.
Вот пример: http://www.javapractices.com/topic/TopicAction.do?Id=32
Но обратите внимание, что рекомендуется использовать статический импорт вместо констант в интерфейсах. Вот ссылка: http://www.javapractices.com/topic/TopicAction.do?Id=195
Ответ 5
Есть ответы, которые очень резонно.
Но у меня есть некоторые мысли по этому вопросу. (может быть не так)
По моему мнению, поля в интерфейсе не должны быть константами для всего проекта, они являются только средствами интерфейса, и интерфейсы расширяют его и классы, которые реализуют эти интерфейсы или имеют с ними тесную связь. Они должны использоваться в определенном диапазоне, а не глобально.
Ответ 6
javax.swing.SwingConstants
- это пример, который получил статические поля, которые используются среди классов swing. Это позволяет легко использовать что-то вроде
-
this.add(LINE_START, swingcomponent);
-
this.add(this.LINE_START, swingcomponent);
или -
this.add(SwingComponents.LINE_START, swingcomponent);
Однако этот интерфейс не имеет методов...
Ответ 7
Я столкнулся с этим вопросом и подумал, что добавлю то, о чем не упоминалось. В общем, я согласен с Pascal ответить здесь. Тем не менее, я не думаю, что константы на интерфейсе "всегда" являются антипаттернами.
Например, если константы, которые вы определяете, являются частью контракта для этот интерфейс, я думаю, что интерфейс - отличное место для констант. В некоторых случаях его просто не подходит для частной проверки ваших параметров, не подвергая контракт пользователям вашей реализации. Без публичного контракта, пользователи могут только догадываться, что вы проверяете, не дожидаясь декомпиляции класса и чтения вашего кода.
Итак, если вы реализуете интерфейс, а интерфейс имеет константы, которые вы используете для обеспечения ваших контрактов (например, целых диапазонов), то пользователь вашего класса может быть уверен, что он правильно использует экземпляр интерфейса, проверяя его на константы в самом интерфейсе. Это было бы невозможно, если бы константы были приватными для вашей реализации или вашей реализации был личный пакет или что-то в этом роде.
Ответ 8
Я сталкивался с этим старым вопросом несколько раз, и принятый ответ все еще смущает меня. После долгих раздумий я думаю, что этот вопрос можно уточнить.
Зачем использовать интерфейс Constant?
Просто сравните их:
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
против
public interface Constants {
public double PI = 3.14159;
public double PLANCK_CONSTANT = 6.62606896e-34;
}
То же использование. Гораздо меньше кода.
Плохая практика?
Я думаю, что ответ @Pascal Thivent имеет неправильный акцент, вот моя версия этого:
Вставка статических членов в интерфейс (и реализация этого интерфейса) - плохая практика.
Цитата из Effective Java предполагает, что другие интерфейсы реализуются постоянным интерфейсом, что, я думаю, не должно (и не будет) происходить.
Когда вы создаете постоянный интерфейс с именем типа Constants
, он не должен реализовываться никем. (хотя технически возможно, что является единственной проблемой здесь)
Это не произойдет в стандартной библиотеке
Стандартная библиотека не может допустить возможного неправильного использования дизайна, поэтому вы просто не увидите там ничего.
Тем не менее, для повседневных проектов обычных разработчиков, использование интерфейса констант намного проще, потому что вам не нужно беспокоиться о static
, final
, empty constructor
и т.д., И это НЕ вызовет проблем с дизайном. Единственный недостаток, о котором я могу думать, это то, что он по-прежнему имеет название "интерфейс", но не более того.
Бесконечные дебаты
В конце концов, я думаю, что все просто цитируют книги и высказывают мнения и оправдания своим позициям. Для меня не исключение. Возможно, решение остается за разработчиками каждого проекта. Просто используйте его, если вам удобно. Лучшее, что мы можем сделать, это сделать его последовательным на протяжении всего проекта.
Ответ 9
Два момента об интерфейсе:
-
Интерфейс описывает подмножество того, что может сделать объект, который его реализует. (Это интуиция)
-
Интерфейс описывает общие константы, за которыми следуют объекты, которые их реализуют.
- Эти общие константы предназначены для того, чтобы клиент знал больше об этих объектах.
- Таким образом, интерфейс констант действительно нелогичен для определения глобальных констант, так как интерфейс используется для описания некоторых объектов, а не всех объектов/никаких объектов (рассмотрим значение глобальных).
Поэтому я думаю, что если интерфейс констант не используется для глобальных констант, то это приемлемо:
- Если эти общие константы имеют хорошие имена, они будут рекомендовать разработчику использовать их (см. Мой первый пункт для примера ниже)
- Если класс хочет синхронизироваться с этими классами в соответствии со спецификацией, просто
implements
его (и, конечно, используйте эти общие константы в реализации).
Пример:
interface Drawable {
double GOLDEN_RATIO = 1.618033988;
double PI = 3.141592653;
...
// methods
...
}
public class Circle implements Drawable {
...
public double getCircumference() {
return 2 * PI * r;
}
}
void usage() {
Circle circle = new Circle(radius: 3.0);
double maxRadius = 5.0;
if ( circle.getCircumference() < 2 * Circle.PI * maxRadius ) {
...
}
}
В этом примере:
- Из
Circle implements Drawable
, вы сразу же знаете, чтоCircle
, вероятно, соответствует константам, определенным вDrawable
, в противном случае им придется выбирать худшее имя, поскольку хорошиеPI
иGOLDEN_RATIO
ужеGOLDEN_RATIO
! - Только эти
Drawable
объекты соответствуют определеннымPI
иGOLDEN_RATIO
определенным вDrawable
, могут быть объекты, которые неDrawable
с разной точностью pi и золотого сечения.
Ответ 10
Я использую интерфейсные константы при работе с общими константами между классами.
public interface TestConstants
{
String RootLevelConstant1 = "RootLevelConstant1";
interface SubGroup1
{
String SubGroupConstant1 = "SubGroup1Constant1";
String SubGroupConstant2 = "SubGroup1Constant2";
}
interface SubGroup2
{
String SubGroupConstant1 = "SubGroup2Constant1";
String SubGroupConstant2 = "SubGroup2Constant2";
}
}
Группирование - огромный актив, особенно с большим набором констант.
Чтобы использовать, вы просто соединяете их вместе:
System.out.println(TestConstants.SubGroup1.SubGroupConstant1);
System.out.println(TestConstants.SubGroup2.SubGroupConstant1);
System.out.println(TestConstants.RootLevelConstant1);
Ответ 11
Полядолжны быть объявлены в интерфейсе, чтобы они были легче share и могут быть указаны без введения дополнительной связи.