Соглашения 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;
};