Соглашения Java для доступных данных. (Public accessors & Getters/Naming)

Через API Java вы видите многочисленные случаи противоречивых имен и практик, которые действительно меня смущают.

Например:

Класс String имеет закрытую переменную (Integer) по имени count, которая отслеживает размер строки, однако это возвращает геттер по имени length().

Если вы перейдете к любому типу массивов, вместо того, чтобы иметь метод getter для длины, они просто передают переменную через общедоступный аксессор, и ее можно получить с помощью arrayInstance.length.

Возвращаясь к классу String, у нас есть метод String#getBytes(), который является геттером, похожим на геттер length(), однако выполняет немного больше логики, чтобы получить и вернуть значение.

Мне лично создание геттера с префиксом get кажется излишним, например, я скорее набираю GamePacket#data() versus GamePacket#getData(), но я чувствую, что за этим наименованием может быть более глубокое значение, а не просто несоответствие.

Кроме того, почему Array[] использует getter для length?

Кто-нибудь был бы любезен, чтобы пролить свет на это для меня?

Ответ 1

Getters (и сеттеры) исходят из спецификации Java Bean. Причины их использования несколько:

  • большинство разработчиков Java ожидают, что аксессоры будут названы так
  • API, соответствующий этим соглашениям, легче обнаружить. Например, в моей среде IDE я часто нажимаю get Ctrl Space, чтобы обнаружить всю информацию, доступную в объекте.
  • многие API и фреймворки полагаются на эти соглашения для работы: структуры JSP EL, MVC, заполняющие beans параметры запроса, JPA, фреймворки зависимостей, такие как Spring и т.д.

Вы обычно называете получателя так же, как и приватную переменную, которая хранит эту информацию, но имеет значение инкапсуляция и публичный API, поэтому ничто не мешает вам вычислять значение в getter или называть частное поле другим путь.

Ответ 2

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

  • Как вам сказали в комментариях, поле length массива final, поэтому оно не может быть установлено.
  • Оба массива и класс String были разработаны в самых ранних версиях Java, прежде чем были согласованы соглашения для геттеров и сеттеров. Соглашения get... is... и set... действительно были решены только при введении JavaBeans. Изменение API заставило бы старый код перестать работать, поэтому старые имена сохраняются.
  • В целом (например, классы, которые не являются JavaBeans), на самом деле нет правила, в котором говорится, что методы getter и setter должны отражать имя какого-либо конкретного поля в классе. Вся идея методов доступа заключается в том, что они скрывают реализацию, поэтому все, что стоит за ними, может быть полем, комбинацией полей или чего-то другого вообще.

Ответ 3

Соглашения об именах, как представляется, различаются по всей кодовой базе Java, но одним ранним стандартом было соглашение об именах JavaBeans; это в основном сформировало номенклатурное решение для Java отсутствия истинных свойств.

Объектные/примитивные геттеры имели форму getXXX(), за исключением булевых, которые имели предпочтительную форму isXXX(). Setters всегда были в форме setXXX().

Из этой единственной точки были написаны миллионы строк отражающего кода.

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

@Setter
void data(Data data) {
    this.data = data;
};

@Getter
Data data() {
    return data;
};