← Назад к вопросам

Почему Setter получил такое название?

1.0 Junior🔥 11 комментариев
#ООП#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему Setter получил такое название

Это классический вопрос о терминологии в Java и ООП. Название "Setter" и "Getter" имеют историческое и практическое происхождение, которое показывает фундаментальные принципы инкапсуляции.

Историческое происхождение

До объектно-ориентированного программирования (1960-70s)

В старых языках типа COBOL, Fortran работали с переменными напрямую:

PROGRAM PrintCobol.
    DATA DIVISION.
        WORKING-STORAGE SECTION.
            01 userName PIC X(50).
    
    PROCEDURE DIVISION.
        MOVE "John" TO userName.  ← Прямое присваивание
        DISPLAY userName.         ← Прямой доступ

Это было просто и быстро, но очень опасно.

Проблемы с прямым доступом:

// Плохой пример: прямой доступ к полям
public class User {
    public int age;  // Публичное поле!
}

// Кто-то в коде делает:
User user = new User();
user.age = -5;  // ❌ Отрицательный возраст?!
user.age = 999; // ❌ Нереальный возраст?!
user.age = 150; // ❌ Вероятно опечатка?

Решение: Encapsulation (инкапсуляция)

ОО языки (Smalltalk, C++, Java) предложили контролировать доступ:

public class User {
    private int age;  // Приватное поле
    
    // Контролируем установку
    public void setAge(int age) {
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("Invalid age");
        }
        this.age = age;
    }
    
    // Контролируем чтение
    public int getAge() {
        return age;
    }
}

// Теперь:
user.setAge(-5);   // ❌ IllegalArgumentException
user.setAge(25);    // ✅ OK
int age = user.getAge();  // ✅ Получаем значение

Почему именно SET и GET

SET — операция установки значения

Представьте физический объект:

У меня есть ящик (объект) с замком (инкапсуляция).
Я не могу просто засунуть руку и положить что-то внутрь.

Вместо этого есть специальный слот (setter):
Я кладу значение в слот setAge(25).
Замок проверяет: "Это реальный возраст? OK, сохраняю внутри."
Если я попробую setAge(-5):
Замок говорит: "Нет! Это невалидно!"

GET — операция получения значения

Если я хочу узнать возраст, я не открываю ящик.
Нет специального окошка (getter): getAge().
Оно показывает мне значение, но я не могу просто так изменить.

От Smalltalk к Java

Smalltalk (1970s) — первый язык, где popularized эти концепции:

" Smalltalk код "
user age: 25.        ← Setter
user age.            ← Getter

Все методы в Smalltalk — это "messages", которые объект получает. Нет концепции "properties" как в Python или C#.

C++ (1980s) стандартизировал naming:

class User {
private:
    int age;
public:
    void setAge(int a) { age = a; }  // Setter
    int getAge() { return age; }     // Getter
};

Java (1995) следовал этому соглашению и популяризировал через JavaBeans:

public class User {
    private int age;
    
    public void setAge(int age) { ... }  // Setter
    public int getAge() { ... }         // Getter
}

Это соглашение стало стандартом де-факто для всей индустрии.

JavaBeans — стандартизация naming

В 1997 году Java придумали JavaBeans specification, которая определила:

Свойство: age (тип: int)

Setter должен быть: setAge(int)
Getter должен быть: getAge()

Вспомогательные методы:
- добавить свойство: addPropertyChangeListener()
- уведомления: firePropertyChange()

Этот стандарт позволил:

  • Reflection-based frameworks (Spring, Hibernate)
  • IDE автоматически генерировать getters/setters
  • Consistent API
@Entity
public class User {
    private Long id;
    private String name;
    private int age;
    
    // IDE может автоматически сгенерировать все getters/setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

Сравнение с другими языками

Python — используют @property

class User:
    def __init__(self):
        self._age = 0
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("Invalid age")
        self._age = value

# Использование:
user.age = 25      # Вызывает setter
print(user.age)    # Вызывает getter

C# — используют Properties

public class User {
    private int _age;
    
    public int Age {
        get { return _age; }
        set {
            if (value < 0) throw new ArgumentException();
            _age = value;
        }
    }
}

// Использование (выглядит как обычное свойство):
user.Age = 25;
int age = user.Age;

Kotlin — используют backing fields

class User {
    var age: Int = 0
        get() { return field }
        set(value) {
            if (value < 0) throw IllegalArgumentException()
            field = value
        }
}

// Использование (как обычное свойство):
user.age = 25
val age = user.age

JavaScript/TypeScript — нет стандартного способа

class User {
    private _age: number = 0;
    
    get age(): number {
        return this._age;
    }
    
    set age(value: number) {
        if (value < 0) throw new Error();
        this._age = value;
    }
}

Почему Java ОСТАЁТСЯ с getXXX/setXXX

1. Историческое наследие

Java решила не делать "syntax sugar" как C# или Python. Методы остаются просто методами.

2. Reflection и инструменты

Spring, Hibernate, Jackson полагаются на JavaBeans соглашение:

// Spring автоматически находит getters/setters
@Component
public class UserComponent {
    private UserService service;
    
    // Spring ищет setUserService!
    @Autowired
    public void setUserService(UserService service) {
        this.service = service;
    }
}

// Hibernate использует getters/setters для маппинга
@Entity
public class User {
    @Id
    private Long id;
    
    // Hibernate будет вызывать getId() / setId()
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
}

// Jackson использует getters/setters для JSON сериализации
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
// Jackson вызывает setters при десериализации

3. Consistency в экосистеме

Все Java frameworki ожидают getXXX/setXXX. Это de facto стандарт.

Логика названий

SET — потому что мы устанавливаем значение

setAge(25):
Веди себя как команда: "Установи возраст на 25"
До этого: age = 10
После: age = 25
Смысл слова SET: "установить, поместить"

GET — потому что мы получаем значение

getAge():
Веди себя как вопрос: "Получи возраст"
Ответ: 25
Смысл слова GET: "получить, взять"

Это очень интуитивные названия для базовых операций.

Когда это может быть проблемой

Исключение: Fluent API

// Стандартный подход
User user = new User();
user.setName("John");
user.setAge(25);
user.setEmail("john@example.com");

// Fluent API (builder pattern)
User user = new User()
    .setName("John")
    .setAge(25)
    .setEmail("john@example.com");

// Для этого setters должны вернуть this
public User setName(String name) {
    this.name = name;
    return this;
}

Исключение: Lombok

@Data  // Автоматически генерирует getters/setters
public class User {
    private String name;
    private int age;
    private String email;
}

// Вместо 50 строк кода, одна аннотация

На собеседовании

Вопрос: "Почему setter получил такое название?"

Хороший ответ:

"Названия SET и GET пришли из истории ООП:

  1. SET — потому что устанавливаем значение в поле (set = установить)
  2. GET — потому что получаем значение из поля (get = получить)

Этот паттерн popularized в Smalltalk (1970s), стандартизирован в Java через JavaBeans specification, и теперь это стандарт де-факто для всей Java индустрии.

Это позволяет:

  • Контролировать доступ (инкапсуляция)
  • Frameworks использовать reflection (Spring, Hibernate)
  • IDE автоматически генерировать методы

Другие языки позже сделали это проще (Python properties, C# properties, Kotlin backing fields), но Java остаётся с явными методами."

Итоговый вывод

SET и GET — это:

✅ Простые, интуитивные названия ✅ Исторически установившийся стандарт ✅ Основа для инкапсуляции в Java ✅ Требование JavaBeans specification ✅ Базис для всех Java frameworks ✅ Lingua franca Java community

Это одно из тех решений, которые вначале казались странными ("Зачем методы вместо properties?"), но со временем доказали свою ценность и стали вечным стандартом.