Геттеры и сеттеры

Если переменная имеет уровень доступа private, к ней невозможно обратиться извне класса, в котором она объявлена. Но все равно необходим способ обращения к private переменным из другого класса, иначе такие изолированные переменные не будут иметь смысла. Это достигается с помощью объявления специальных public методов. Методы, которые возвращают значение переменных, называются геттеры. Методы, которые изменяют значение свойств, называются сеттеры.

Существуют правила объявления таких методов, рассмотрим их:

  1. Если свойство НЕ типа boolean, префикс геттера должно быть get. Например: getName() это корректное имя геттера для переменной name.
  2. Если свойство типа boolean, префикс имени геттера может быть get или is. Например, getPrinted() или isPrinted() оба являются корректными именами для переменных типа boolean.
  3. Имя сеттера должно начинаться с префикса set. Например, setName() корректное имя для переменной name.
  4. Для создания имени геттера или сеттера, первая буква свойства должна быть изменена на большую и прибавлена к соответствующему префиксу (set, get или is).
  5. Сеттер должен быть public, возвращать void тип и иметь параметр соответствующий типу переменной. Например:
    public void setAge(int age) {
        this.age = age;
    }​
  6. Геттер метод должен быть public, не иметь параметров метода, и возвращать значение соответствующее типу свойства. Например: 
    public int getAge() {
        return 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;
    }
}
public class PersonDemo {
    public static void main(String[] args) {
        Person person = new Person();
        person.setFullName("Петров Иван Иванович");
        person.setAge(56);
        person.setRetired(false);

        System.out.println("Полное имя " + person.getFullName());
        System.out.println("Возраст " + person.getAge());
        System.out.println("Пенсионер? " + person.isRetired());
    }
}

Геттеры и сеттеры делают код более громоздким, поэтому часто задается вопрос о том, можно ли обойтись без них. Объясню их необходимость на следующих двух примерах.

Рассмотрим класс CircleWrong, у которого две переменные - радиус и диаметр, объявленные с уровнем доступа по умолчанию.

public class CircleWrong {
    int radius;
    int diam;
}

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

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;
    }
}

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

public class CircleDemo {
    public static void main(String[] args) {
        Circle circle = new Circle();
        circle.setDiam(25);
        circle.setRadius(10);

        System.out.println(circle.getDiam());
        System.out.println(circle.getRadius());
    }
}

В следующем примере рассмотрим возможности геттера. Класс 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;
    }
}
public class UserDemo {
    public static void main(String[] args) {
        User user = new User("mylogin", "mypassword");
        System.out.println("Логин: " + user.getLogin());
        System.out.println("Пароль: " + user.getPassword());
    }
}

Результат выполнения:

Логин: mylogin
Пароль: m*****
Read also:
Comments