Соглашение об именах: конечные поля (не статические)

23

Сегодня у меня была дискуссия с коллегой по поводу именования finalполей в классах Java.

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

Это приведет к следующему соглашению об именах для finalполей:

public class Foo {
    private static final String BLA_BLA = "bla";

    private final String BAR_BATZ;

    ...
}

По моему мнению, только static finalполя должны считаться константами, в то время как поля, которые только finalдолжны следовать обычному соглашению об именах camelCase.

public class Foo {
    private static final String BLA = "bla";

    private final String barBatz;

    ...
}

Теперь я немного неуверен, поскольку он гораздо более опытный программист, чем я, и я обычно согласен с его мнением и считаю его очень хорошим разработчиком.

Любой вклад в это?

Саша Волк
источник
Ваши примеры не являются постоянными; вы не присваивали им значения во время компиляции. Следовательно, они не следуют соглашениям по именованию констант.
Роберт Харви
@RobertHarvey Спасибо, вы правы. Он ...должен был символизировать любой возможный конструктор, который устанавливает finalполе, но это явно невозможно для static finalполя.
Саша Вольф
1
@Zeeker Вас могут заинтересовать static { }блоки, которые можно использовать для установки статических полей в классе один раз при загрузке класса. Связанные Работа со статическим конструктором в Java .
@RobertHarvey Я с ними знаком. Но, тем не менее, спасибо.
Саша Вольф
1
Я бы сказал, что поскольку переменная принадлежит экземпляру, она будет отличаться от экземпляра к экземпляру, поэтому она не применяется как константа. Я бы использовал чехол для верблюда.
Florian F

Ответы:

20

Sun (а теперь и Oracle) поддерживает документ под названием « Соглашения по коду для языка программирования Java» . Последнее обновление этого было в '99, но суть линии руководства по стилю живет.

Глава 9 охватывает соглашения об именах.

Для типа идентификатора «константы»:

Имена переменных, объявленных как константы класса, так и констант ANSI должны быть в верхнем регистре со словами, разделенными подчеркиванием ("_"). (Следует избегать использования констант ANSI для простоты отладки.)

Приведенные примеры:

static final int MIN_WIDTH = 4;

static final int MAX_WIDTH = 999;

static final int GET_THE_CPU = 1;

В более свежем документе - он проскользнул туда. Из переменных (Учебные руководства Java> Изучение языка Java> Основы языка :

Если выбранное вами имя состоит только из одного слова, пишите это слово строчными буквами. Если оно состоит из более чем одного слова, используйте заглавные буквы первой буквы каждого последующего слова. Имена gearRatioи currentGearявляются яркими примерами этого соглашения. Если ваша переменная хранит постоянное значение, например static final int NUM_GEARS = 6, соглашение изменяется незначительно, используя заглавные буквы и разделяя последующие слова символом подчеркивания. По соглашению символ подчеркивания никогда не используется в другом месте.

Многие статические анализаторы для Java стремятся обеспечить это. Например, checkstyle обеспечивает:

Проверяет, что имена констант соответствуют формату, указанному в свойстве format. Константа - это статическое и конечное поле или поле интерфейса / аннотации, кроме serialVersionUIDи serialPersistentFields. Формат является регулярным выражением и по умолчанию ^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$.


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

Приведенные выше примеры даны как примеры static final, которые, вероятно, получены из соглашений C, для #defineкоторых, как и C, заменяются в коде во время компиляции, а не во время выполнения.

Вопрос, который следует задать: «Это ведет себя как константа? Или оно ведет себя как поле однократной записи?» - и затем, следуя конвенциям, соответственно. Лакмусовая бумажка для такого вопроса будет такой: «Если бы вы сериализовали объект, включили бы вы последнее поле?» Если ответ таков: это константа, тогда относитесь к ней как к таковой (и не сериализуйте ее). С другой стороны, если это часть состояния объекта, которую необходимо сериализовать, то это не константа.

В любом случае важно придерживаться стиля кода, каким бы правильным или неправильным он ни был. Хуже проблемы возникают из-за непоследовательных соглашений в проекте, а не просто из-за того, что оскорбляет глаз. Подумайте о приобретении некоторых инструментов статического анализа и настройте их для обеспечения согласованности.


источник
@RobertHarvey Я мог бы представить себе некоторые ситуации, когда поле экземпляра ведет себя как константа. Фабрика, например, заполняет что-то, что в противном случае было бы константой в объекте ... хотя это приводит к довольно надуманным примерам, которые повреждают мою голову, просто думая о том, почему кто-то это сделает.
Спасибо за этот подробный ответ. Лакмусовая бумажка о сериализации объекта сделала для меня сделку.
Саша Вольф
Недавно один коллега подтвердил, что когда-то редакторы не очень хорошо выделяли статические / статические финалы и т. Д., Поэтому это соглашение об именах было важным. В наши дни IDE довольно хороши, поэтому мы можем сделать для них более привлекательные имена, например: MinWidthвместо MIN_WIDTH. Другой вопрос: как насчет статических финальных регистраторов? Вы называете их LOG/ LOGGERили log/ logger. Лично logвыглядит лучше в соответствии с кодом, но когда допустимо несоответствие, если вообще?
ndtreviv
5

BAR_BATZне является константой в этом примере. Конструкторы Fooмогут устанавливать различные значения на уровне объекта. Например

public class Foo {
    private final String BAR_BATZ;

    Foo() {
       BAR_BATZ = "ascending";
    } 

    Foo(String barBatz) {
       BAR_BATZ = barBatz;
    }
}
Kirby
источник