Геттеры и сеттеры
Если переменная имеет уровень доступа private , к ней невозможно обратиться извне класса, в котором она объявлена. Но все равно необходим способ обращения к private переменным из другого класса, иначе такие изолированные переменные не будут иметь смысла. Это достигается с помощью объявления специальных public методов. Методы, которые возвращают значение переменных, называются геттеры. Методы, которые изменяют значение свойств, называются сеттеры.
Существуют правила объявления таких методов, рассмотрим их:
- Если свойство НЕ типа boolean , префикс геттера должно быть get. Например: getName() это корректное имя геттера для переменной name .
- Если свойство типа boolean , префикс имени геттера может быть get или is . Например, getPrinted() или isPrinted( ) оба являются корректными именами для переменных типа boolean .
- Имя сеттера должно начинаться с префикса set. Например, setName() корректное имя для переменной name .
- Для создания имени геттера или сеттера, первая буква свойства должна быть изменена на большую и прибавлена к соответствующему префиксу ( set , get или is ).
- Сеттер должен быть public , возвращать void тип и иметь параметр соответствующий типу переменной. Например:
public void setAge(int age) < this.age = age; >
В языке Java при проектировании классов принято ограничивать уровень доступа к переменным с помощью модификаторов private или protected и обращаться к ним через геттеры и сеттеры.
Существует также такое понятие как JavaBeans классы — это классы содержащие свойства. В Java мы можем рассматривать свойства как private переменные класса. Так как они private , доступ к ним извне класса может быть осуществлен только с помощью методов класса.
Рассмотрим пример реализации концепции JavaBeans на классе Person , у которого есть три переменные. Они объявлены как private и доступ к ним возможен только через соответствующие геттеры и сеттеры
public class Person < private String fullName; private int age; private boolean retired; public Person() < >public Person(String fullName, int age, boolean retired) < this.fullName = fullName; this.age = age; this.retired = retired; >public String getFullName() < return fullName; >public void setFullName(String fullName) < this.fullName = fullName; >public int getAge() < return age; >public void setAge(int age) < this.age = age; >public boolean isRetired() < return retired; >public void setRetired(boolean retired) < this.retired = retired; >>
Геттеры и сеттеры делают код более громоздким, поэтому часто задается вопрос о том, можно ли обойтись без них. Объясню их необходимость на следующих двух примерах.
Рассмотрим класс CircleWrong , у которого две переменные — радиус и диаметр, объявленные с уровнем доступа по умолчанию.
Любой класс в том же пакете может обратиться к ним напрямую и изменить их значение. Значения этих двух переменных должно соответствовать друг другу, но пользователь этого класса может задать любые значения, например:
public class CircleWrongDemo < public static void main(String[] args) < CircleWrong circle = new CircleWrong(); circle.diam = 25; circle.radius = 10; System.out.println("Диаметр: " + circle.diam); System.out.println("Радиус: " + circle.radius); >>
Это может привести к неправильным дальнейшим вычислениям. Перепишем этот класс с использованием концепции JavaBeans, но немного изменим сеттеры. Метод setRadius() вместе с радиусом задает правильное значение для диаметра. Метод setDiam() написан соответствующим образом:
public class Circle < private int radius; private int diam; public int getRadius() < return radius; >public void setRadius(int radius) < this.radius = radius; this.diam = radius * 2; >public int getDiam() < return diam; >public void setDiam(int diam) < this.diam = diam; this.radius = diam / 2; >>
Пользователь данного класса не может напрямую добраться к переменным, доступ осуществляется только через сеттеры, где мы контролируем правильную установку значений нашим переменным:
В следующем примере рассмотрим возможности геттера. Класс User содержит две переменные — логин и пароль. Пароль содержит чувствительную информацию, которую не рекомендуется показывать. Достигается это с помощью объявления переменной с модификатором private и доступом к ней только через геттер метод, в котором вместо полного пароля показываем только первую букву, а остальные заменяются звездочками:
public class User < private String login; private String password; public User(String login, String password) < this.login = login; this.password = password; >public String getLogin() < return login; >public void setLogin(String login) < this.login = login; >public String getPassword() < return password.charAt(0) + "*****"; >public void setPassword(String password) < this.password = password; >>
Пример геттера и сеттера java
Как вы заметили, 2-й элемент массива scores изменяется вне сеттера (в строке 5). Поскольку геттер возвращает ссылку на scores, внешний код, имея эту ссылку, может вносить изменения в массив.
Решение этой проблемы заключается в том, что геттеру необходимо возвращать копию объекта, а не ссылку на оригинал. Модифицируем вышеупомянутый геттер следующим образом:
Переменные примитивных типов вы можете свободно передавать/возвращать прямо в сеттере/геттере, потому что Java автоматически копирует их значения. Таким образом, ошибок № 2 и № 3 можно избежать.
private float amount; public void setAmount(float amount) < this.amount = amount; >public float getAmount()
String — это immutable-тип. Это означает, что после создания объекта этого типа, его значение нельзя изменить. Любые изменения будут приводить к созданию нового объекта String. Таким образом, как и для примитивных типов, вы можете безопасно реализовать геттер и сеттер для переменной String:
private String address; public void setAddress(String address) < this.address = address; >public String getAddress()
Т.к. объекты класса java.util.Date являются изменяемыми, то внешние классы не должны иметь доступ к их оригиналам. Данный класс реализует метод clone() из класса Object, который возвращает копию объекта, но использовать его для этих целей не стоит.
По этому поводу Джошуа Блох пишет следующее: «Поскольку Date не является окончательным классом, нет гарантии, что метод clone() возвратит объект, класс которого именно java.util.Date: он может вернуть экземпляр ненадежного подкласса, созданного специально для нанесения ущерба. Такой подкласс может, например, записывать ссылку на каждый экземпляр в момент создания последнего в закрытый статический список, а затем предоставить злоумышленнику доступ к этому списку. В результате злоумышленник получит полный контроль над всеми экземплярами копий. Чтобы предотвратить атаки такого рода, не используйте метод clone() для создания копии параметра, тип которого позволяет ненадежным сторонам создавать подклассы».
Пример геттера и сеттера java
Я писал интересные коменты с байтом на лайки, и не интересные без байтов, я уже сплю плохо из за этой ачивки, налайкайте пожалуйста этот коммент до 10 😬😬
Для самых ленивых в IDEA есть возможность автоматом создавать сеттеры геттеры equals и тд. Нажмите правой кнопкой по редактору и выберите generate. Или хоткеем : «alt + insert» то же самое сделайте.
Геттеры (getter methods) и сеттеры (setter methods) — это методы, которые используются для получения и установки значений инкапсулированных переменных (полей класса) в Java. В объектно-ориентированном программировании (ООП) инкапсуляция (encapsulation) — это механизм, который позволяет скрыть детали реализации и предоставить доступ к объектам только через публичный интерфейс. Инкапсуляция достигается с помощью классов, которые могут определять поля и методы. Поля (или переменные) являются хранилищем данных класса, а методы позволяют работать с этими данными. Однако, если поля класса определены с модификатором доступа private, то они могут быть доступны только внутри класса, что предотвращает прямой доступ к этим полям извне. В этом случае для получения и установки значений полей используются геттеры и сеттеры. Геттеры Геттеры — это методы, которые используются для получения значения инкапсулированных полей. Обычно называются с префиксом «get», за которым следует имя поля, первая буква имени поля должна быть заглавной. Например, для поля name может быть определен геттер следующим образом: «` public String getName() < return name; >«` Этот метод возвращает значение поля name. Сеттеры Сеттеры — это методы, которые используются для установки значения инкапсулированных полей. Обычно называются с префиксом «set», за которым следует имя поля, первая буква имени поля должна быть заглавной. Также сеттеры часто возвращают void. Например, для поля name может быть определен сеттер следующим образом: «` public void setName(String name) < this.name = name; >«` Этот метод устанавливает значение поля name. Геттеры и сеттеры могут быть полезными, когда необходимо контролировать доступ к полям класса. Это также помогает сделать класс более безопасным и уменьшить возможность ошибок при использовании класса.context
Пример геттера и сеттера java
Вопрос, почему мы не задаем в конструкторе класса значение через сеттер (в котором выполнена проверка на валидность), а задаем что-то типа this.value = value (вместо setValue(value)) ?? Ниже написал код в виде примера. Если бы в конструкторе было this.value = value, то при инициализации объекта значением например -3 в конструкторе всё было бы ОК. А сеттер в конструкторе не даст сделать такой глупости.
public class Main < public static void main(String[] args) < //это значение не вызовет ошибку, пока оно положительное: MyClass myClass = new MyClass(3); //MyClass myClass = new MyClass(-3) //тут будет ошибка! myClass.setValue(4); //это значение не вызовет ошибку //myClass.setValue(-4); //а это вызовет ошибку! System.out.println(myClass.getValue()); >> class MyClass < private int value; public MyClass(int value) < setValue(value); >public int getValue() < return value; >public void setValue(int value) < if (value < 0) < throw new IllegalArgumentException ("Значение value должно быть положительным числом!"); >this.value = value; > >
Для быстрого создания getter и setter в IntelliJ IDEA выделяете переменную класса и нажимаете alt + insert, во всплывшем окошке можно выбрать что хотите создать.
Интересно, почему в гетере пишут просто return name а можно написать так public String getName() < return this.name; >потому что так просто короче? Или функционал меняется?
Что-то я не совсем понял, даже если я объявил переменную класса private но создал сеттер, то мой объект извне можно все равно изменять, разница лишь в проверке значений. А если я не хочу чтобы мой объект изменяли, то я просто не пишу сеттер? Но смогу ли я сам менять значения объекта?
в конструкторе ведь то же можно указать ограничения при создании объекта?,и еще вопрос в Idea можно изменить название переменной сделав пару кликов,и оно меняется везде в коде вот эта замена это аналог замены через сеттер без потери потерь или там более простая логика и он тупо меняет названия?
А если я при создании объекта передам не корректные значения? Cat barsik = new Cat(«noname», -1000, 1000); Надо ли делать валидацию в конструкторе?
Геттеры и Сеттеры
Следующее понятие из мира ООП, которое следует рассмотреть — это геттеры и сеттеры (getter — от англ. «get» — получать, и setter — от англ. «set» — устанавливать). Это общепринятый способ вводить данные («set») или получать данные («get»). Например, у меня есть класс Cat — кошка. Я задаю (используя setter) имя, пол, цвет глаз и окрас кошки (или кота):
А потом, если нужно узнать, какое у кошки имя — получаю с помощь getter — в данном случае get CatName :
Зачем они нужны?
Действительно — если я сам все задаю, зачем все эти геттеры и сеттеры?
Тут, нам стоит вспомнить про такой принцип ООП как инкапсуляция (если Вы не знаете, что это такое, вернитесь назад и прочитайте статью «Что такое ООП»). С помощью геттеров и сеттеров Вы защищаете содержимое программы — когда ей пользуется кто-то другой.
Представим, что создается программа, с помощью которой печатаются паспорта. Вам ведь не захочется, чтобы кто-то без доступа вносил изменения в эту программу?
Как это работает?
Итак, как уже стало понятно, геттеры и сеттеры выполняют важную миссию защиты данных Вашей программы. Давайте рассмотрим, как это происходит на практике, и представим, что у нас есть такой класс Cat: