Java Language
Геттеры и сеттеры
В этой статье обсуждаются геттеры и сеттеры; стандартный способ обеспечения доступа к данным в Java-классах.
Добавление геттеров и сеттеров
Инкапсуляция является базовой концепцией в ООП. Речь идет об обертывании данных и кода в виде единого блока. В этом случае рекомендуется объявлять переменные как private а затем обращаться к ним через Getters и Setters для просмотра и / или изменения их.
public class Sample < private String name; private int age; public int getAge() < return age; >public void setAge(int age) < this.age = age; >public String getName() < return name; >public void setName(String name) < this.name = name; >>
Эти частные переменные не могут быть доступны непосредственно извне класса. Следовательно, они защищены от несанкционированного доступа. Но если вы хотите просмотреть или изменить их, вы можете использовать Getters и Setters.
getXxx() вернет текущее значение переменной xxx , в то время как вы можете установить значение переменной xxx с помощью setXxx() .
Соглашение об именах методов (в переменной example называется variableName ):
getVariableName() //Getter, The variable name should start with uppercase setVariableName(..) //Setter, The variable name should start with uppercase
isVariableName() //Getter, The variable name should start with uppercase setVariableName(. ) //Setter, The variable name should start with uppercase
Публичные Getters и Setters являются частью определения свойства Java Bean.
Использование сеттера или геттера для реализации ограничения
Setters и Getters позволяют объекту содержать частные переменные, к которым можно получить доступ и изменить с ограничениями. Например,
public class Person < private String name; public String getName() < return name; >public void setName(String name) < if(name!=null && name.length()>2) this.name = name; > >
В этом классе Person есть единственная переменная: name . К этой переменной можно обратиться с помощью getName() и изменить с помощью setName(String) , однако для установки имени требуется, чтобы новое имя имеет длину более 2 символов и не должно быть нулевым. Использование метода setter вместо того, чтобы публиковать name переменной, позволяет другим устанавливать значение name с определенными ограничениями. То же самое можно применить к методу геттера:
public String getName()< if(name.length()>16) return "Name is too large!"; else return name; >
В модифицированном getName() выше name возвращается, только если его длина меньше или равна 16. В противном случае возвращается «Name is too large» . Это позволяет программисту создавать переменные, которые достижимы и могут быть изменены, но, тем не менее, они препятствуют нежелательным редактированию переменных.
Зачем использовать Getters и Setters?
Рассмотрим базовый класс, содержащий объект с геттерами и сеттерами в Java:
public class CountHolder < private int count = 0; public int getCount() < return count; >public void setCount(int c) < count = c; >>
Мы не можем получить доступ к переменной count потому что она закрыта. Но мы можем получить доступ к методам getCount() и setCount(int) потому что они общедоступны. Для некоторых это может поставить вопрос; зачем вводить посредника? Почему бы просто просто не считать их общедоступными?
Для всех целей и задач эти два являются точно такими же, функционально. Разница между ними — расширяемость. Подумайте, что говорит каждый класс:
- Во-первых : «У меня есть метод, который даст вам значение int и метод, который установит это значение для другого int ».
- Во-вторых : «У меня есть int который вы можете установить и получить, как пожелаете».
Они могут казаться похожими, но первый на самом деле гораздо более защищен по своей природе; он только позволяет вам взаимодействовать с его внутренней природой, как она диктует. Это оставляет мяч в его суде; он выбирает, как происходят внутренние взаимодействия. Вторая сторона внесла свою внутреннюю реализацию извне и теперь не только подвержена внешним пользователям, но, в случае API, привержена поддержке этой реализации (или иным образом освобождает API, не поддерживающий обратную совместимость).
Давайте рассмотрим, хотим ли мы синхронизировать доступ к изменению и доступу к счету. Во-первых, это просто:
public class CountHolder < private int count = 0; public synchronized int getCount() < return count; >public synchronized void setCount(int c) < count = c; >>
но во втором примере это становится практически невозможным без прохождения и изменения каждого места, на которое ссылается переменная count . Что еще хуже, если это элемент, который вы предоставляете в библиотеке, которую вы будете потреблять другими, у вас нет способа выполнить эту модификацию и вынуждены сделать жесткий выбор, упомянутый выше.
Поэтому он задает вопрос; являются ли общедоступные переменные когда-либо хорошей (или, по крайней мере, не злой)?
Я не уверен. С одной стороны, вы можете увидеть примеры открытых переменных, которые выдержали проверку времени (IE: переменная out ссылается System.out ). С другой стороны, предоставление публичной переменной не приносит пользы за пределы чрезвычайно минимальных накладных расходов и потенциального сокращения словесности. Мое руководство здесь будет состоять в том, что если вы планируете делать переменную публику, вы должны судить об этом против этих критериев с крайним предрассудком:
- Переменные не должны иметь никаких мыслимых оснований когда — либо изменений в его реализации. Это очень легко повредить (и, даже если вы все исправите, требования могут измениться), поэтому геттеры / сеттеры — общий подход. Если у вас будет общедоступная переменная, это действительно нужно продумать, особенно если она будет выпущена в библиотеке / framework / API.
- На переменную нужно ссылаться достаточно часто, чтобы гарантировать минимальный выигрыш от сокращения подробностей. Я даже не думаю, что накладные расходы на использование метода в сравнении с прямой ссылкой должны рассматриваться здесь. Это слишком незначительно для того, что я с консервативной оценкой должен составлять 99,9% приложений.
Там, наверное, больше, чем я не рассматривал с головы. Если вы когда-либо сомневаетесь, всегда используйте геттеры / сеттеры.
- Начало работы с Java Language
- 2D-графика в Java
- Apache Commons Lang
- API Reflection
- API стека
- AppDynamics и TIBCO BusinessWorks для легкой интеграции
- Autoboxing
- BigDecimal
- BigInteger
- BufferedWriter
- ByteBuffer
- CompletableFuture
- Enum, начиная с номера
- FileUpload для AWS
- FTP (протокол передачи файлов)
- HttpURLConnection
- InputStreams и OutputStreams
- Java Pitfalls — использование исключений
- Java Pitfalls — синтаксис языка
- JavaBean
- Java-агенты
- Java-версии, версии, выпуски и дистрибутивы
- JAXB
- JAX-WS
- JMX
- JNDI
- JShell
- JSON в Java
- LinkedHashMap
- log4j / log4j2
- NIO — Сеть
- NumberFormat
- ServiceLoader
- SortedMap
- Streams
- StringBuffer
- StringBuilder
- sun.misc.Unsafe
- ThreadLocal
- TreeMap и TreeSet
- Varargs (переменный аргумент)
- WeakHashMap
- XJC
- XOM — Объектная модель XML
- Альтернативные коллекции
- Анализ XML с использованием API JAXP
- Аннотации
- Апплеты
- Атомные типы
- аудио
- Безопасность и криптография
- Безопасность и криптография
- Бит-манипуляция
- Валюта и деньги
- Ведение журнала (java.util.logging)
- Видимость (контроль доступа к членам класса)
- Виртуальная машина Java (JVM)
- Виртуальный доступ Java
- Вложенные и внутренние классы
- Возможности Java SE 7
- Возможности Java SE 8
- Выбор коллекций
- Выражения
- Генерация случайных чисел
- Геттеры и сеттеры
- Даты и время (java.time. *)
- Двигатель JavaScript Nashorn
- Дженерики
- Документирование кода Java
- Загрузчики классов
- Защищенные объекты
- Изменение байтового кода
- Инкапсуляция
- Интерфейс Dequeue
- Интерфейс Java Native
- Интерфейс инструмента JVM
- Интерфейсы
- Исключения и обработка исключений
- Исполнители, Исполнительные службы и пулы потоков
- Использование ThreadPoolExecutor в приложениях MultiThreaded.
- Использование других языков сценариев в Java
- Использование ключевого слова static
- Итератор и Итерабель
- Календарь и его подклассы
- Карта Enum
- Карты
- Класс — отражение Java
- Класс EnumSet
- Класс java.util.Objects
- Класс даты
- Класс свойств
- Классы и объекты
- Клонирование объектов
- Кодировка символов
- Коллекции
- Команда Java — «java» и «javaw»
- Команды выполнения
- Компилятор Java — «javac»
- Компилятор Just in Time (JIT)
- Консольный ввод-вывод
- Конструкторы
- литералы
- Локализация и интернационализация
- Лямбда-выражения
- Массивы
- Менеджер по безопасности
- Местное время
- Местный внутренний класс
- Методы и конструкторы классов объектов
- Методы по умолчанию
- Методы сбора коллекции
- Модель памяти Java
- Модификаторы без доступа
- Модули
- наборы
- наследование
- Настройка производительности Java
- Неизменяемые объекты
- Неизменяемый класс
- Необязательный
- Новый ввод-вывод файлов
- Обработка аргументов командной строки
- Общие ошибки Java
- Одиночки
- операторы
- Операции с плавающей точкой Java
- Ориентиры
- Основные управляющие структуры
- Отправка динамического метода
- Оценка XML XPath
- Очереди и Deques
- Ошибки Java — Nulls и NullPointerException
- Ошибки Java — потоки и параллелизм
- Ошибки Java — проблемы с производительностью
- пакеты
- Параллельное программирование (темы)
- Параллельное программирование с использованием структуры Fork / Join
- Параллельные коллекции
- Перечисления
- Полиморфизм
- предпочтения
- Преобразование в строки и из них
- Преобразование типа
- Примитивные типы данных
- Процесс
- Путь Класса
- Разборка и декомпиляция
- Развертывание Java
- Разделение строки на части с фиксированной длиной
- Реализации Java-плагинов
- Регулярные выражения
- Рекурсия
- Ресурсы (на пути к классам)
- Розетки
- Свободный интерфейс
- Сериализация
- сетей
- сканер
- Служба печати Java
- Создание изображений программно
- Создание кода Java
- Сокеты Java
- Списки
- Список против SET
- Сравнение C ++
- Сравнительный и компаратор
- Ссылки на объекты
- Стандарт официального кода Oracle
- Строковый токенизатор
- Струны
- супер ключевое слово
- Тестирование устройства
- Типы ссылок
- Типы ссылочных данных
- Удаленный вызов метода (RMI)
- Управление памятью Java
- Установка Java (стандартная версия)
- Утверждая
- Файловый ввод-вывод
- Файлы с несколькими релизами JAR
- Флаги JVM
- Функциональные интерфейсы
- Хеш-таблица
- Читатели и писатели
- Шифрование RSA
Геттеры в классах 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() для создания копии параметра, тип которого позволяет ненадежным сторонам создавать подклассы».