Инкапсуляция java что это
Инкапсуляция в Java
Что такое инкапсуляция
С помощью инкапсуляции мы защищаем данные от неправомерного использования.
Если еще проще
Как применяется инкапсуляция
Есть несколько способов регулировать доступ к нашим данным. Основные это:
Модификаторы доступа
Существуют четыре модификатора доступа:
На самом деле по названиям не сложно понять, что каждый из них означает:
Модификаторы доступа пишутся перед названиями переменных, методов и даже классов:
Инкапсуляция java что это
Основой инкапсуляции в Java является класс. Класс определяет данные и код некоторого набора объектов. Объект является экземпляром класса. Таким образом, класс — это логическая конструкция, а объект – физическая реальность.
При составлении класса код и данные необходимо специфицировать. Все эти элементы называют членами класса. Члены-переменные или переменные экземпляра являются данными. Члены методы или просто методы – код, оперирующий этими данными.
Цель класса – инкапсуляция сложности. Для этого у методов и переменных внутри класса могут быть модификаторы доступа (public, private).
Инкапсуляция означает, что данные объекта недоступны его клиентам непосредственно. Вместо этого они инкапсулируются — скрываются от прямого доступа извне. Инкапсуляция предохраняет данные объекта от нежелательного доступа, позволяя объекту самому управлять доступом к своим данным.
Модификаторы доступа
Модификаторы доступа можно рассматривать как с позиции инкапсуляции так и наследования. Если рассматривать с позиции инкапсуляции, то модификаторы доступа позволяют ограничить нежелательный доступ к членам класса извне.
Модификатор доступа | Область доступа |
public | Без ограничений |
private | Только из данного класса |
protected | Из данного класса и его потомков |
Без модификатора | Для всех классов данного пакета |
Открытые члены класса составляют внешнюю функциональность, которая доступна другим классам. Закрытыми (private) обычно объявляются независимые от внешнего функционала члены, а также вспомогательные методы, которые являются лишь деталями реализации и не универсальны по своей сути. Благодаря сокрытию реализации класса можно менять внутреннюю логику отдельного класса, не меняя код остальных компонентов системы.
Очень часто программистами используется доступ к свойствам класса только через его методы (принцип bean классов), который позволяет валидировать значения полей, так как прямое обращение к свойствам отслеживать крайне сложно, а значит им могут присваиваться некорректные значения на этапе выполнения программы. Такой принцип относится к управлению инкапсулированными данными и позволяет быстро изменить способ хранения данных. Если данные станут храниться не в памяти, а в файлах или базе данных, то потребуется изменить лишь ряд методов одного класса, а не вводить эту функциональность во все части системы.
Программный код, написанный с использованием этого принципа легче отлаживать. Для того чтобы узнать, в какой момент времени и кто изменил свойство интересующего нас объекта, достаточно добавить вывод отладочной информации в тот метод объекта, посредством которого осуществляется доступ к свойству этого объекта. При использовании прямого доступа к свойствам объектов программисту бы пришлось добавлять вывод отладочной информации во все участки кода, где используется интересующий нас объект.
Автоупаковка (outboxing)
В Java 2 5.0 введена автоупаковка примитивов. Автоупаковка – это процесс автоматической инкапсуляции данных примитива (простого типа) в эквивалентную объектную оболочку типа. Автоупаковка примитива в объектную оболочку требуется потому, что примитивы лежат вне иерархии классов. Чаще всего процесс автоупаковки необходим при работе с коллекциями, так как коллекции оперируют объектами.
До появления автоупаковки процесс упаковки производился вручную с помощью операции new, например:
С помощью автоупаковки, введенной в версии 5.0 создание объекта явно не происходит, инкапсуляция происходит автоматически:
При этом нет необходимости в явном создании объекта нужного типа.
Модификаторы — ключевые слова, которые вы добавляете при инициализации для изменения значений. Язык Java имеет широкий спектр модификаторов, основные из них:
Чтобы использовать модификатор в Java, нужно включить его ключевое слово в определение класса, метода или переменной. Модификатор должен быть впереди остальной части оператора, как показано в следующих примерах:
Модификаторы доступа
Java предоставляет ряд модификаторов доступа, чтобы задать уровни доступа для классов, переменных, методов и конструкторов. Существует четыре доступа:
Модификатор доступа по умолчанию — без ключевого слова
Модификатор доступа по умолчанию — означает, что мы явно не объявляем модификатор доступа в Java для класса, поля, метода и т.д.
Переменная или метод, объявленные без модификатора контроля доступа доступны для любого другого класса в том же пакете. Поля в интерфейсе неявно являются public, static, final, а методы в интерфейсе по умолчанию являются public.
Переменные и методы могут быть объявлены в Java без каких-либо модификаторов, как показано в следующем примере:
Модификатор доступа private
Модификатор private — методы, переменные и конструкторы, которые объявлены как private в Java могут быть доступны только в пределах самого объявленного класса.
Модификатор доступа private является наиболее ограничивающим уровенем доступа. Класс и интерфейсы не могут быть private.
Переменные, объявленные как private, могут быть доступны вне класса, если получающие их открытые (public) методы присутствуют в классе (ниже смотрите пример и пояснения).
Использование модификатора private в Java является основным способом, чтобы скрыть данные.
Следующий класс использует контроль доступа private:
Здесь переменная format класса Logger является private, так что нет никакого способа для других классов, чтобы получить и установить её значение напрямую.
Таким образом, чтобы эта переменная была доступна для всего, мы определили два открытых (public) метода: getFormat(), который возвращает значение format, и setFormat(String), который устанавливает её значение.
Модификатор доступа public
Модификатор public — класс, метод, конструктор, интерфейс и т.д. объявленные как public могут быть доступны из любого другого класса. Поэтому поля, методы, блоки, объявленные внутри public класса могут быть доступны из любого класса, принадлежащего к «вселенной» Java.
Тем не менее, если к public классу в другом пакете мы пытаемся получить доступ, то public класс приходится импортировать.
Благодаря наследованию классов, в Java все публичные (public) методы и переменные класса наследуются его подклассами.
Следующая функция использует контроль доступа public:
Метод main() должен быть публичным (public). В противном случае, он не может быть вызван с помощью java-интерпретатора, чтобы запустить класс.
Модификатор доступа protected
Модификатор protected — переменные, методы и конструкторы, которые объявляются как protected в суперклассе, могут быть доступны только для подклассов в другом пакете или для любого класса в пакете класса protected.
Модификатор доступа protected в Java не может быть применен к классу и интерфейсам. Методы и поля могут быть объявлены как protected, однако методы и поля в интерфейсе не могут быть объявлены как protected.
Доступ protected дает подклассу возможность использовать вспомогательный метод или переменную, предотвращая неродственный класс от попыток использовать их.
Следующий родительский класс используется для контроля доступа protected, чтобы его дочерний класс переопределил метод openSpeaker() :
При этом, если мы определим метод openSpeaker() как protected, то он не будет доступен из любого другого класса, кроме AudioPlayer. Если мы определим его как public, то он станет доступным всем. Но наше намерение состоит в том, чтобы раскрыть этот метод только подклассу, вот почему мы использовали модификатор protected.
Правила контроля доступа и наследования
Следующие правила в Java применяются для унаследованных методов:
Модификаторы класса, метода, переменной и потока, используемые не для доступа
Java предоставляет ряд модификаторов не для доступа, а для реализации многих других функциональных возможностей:
Модификатор static
Модификатор static — применяется для создания методов и переменных класса.
Переменные static
Ключевое слово static используется для создания переменных, которые будут существовать независимо от каких-либо экземпляров, созданных для класса. Только одна копия переменной static в Java существует вне зависимости от количества экземпляров класса.
Статические переменные также известны как переменные класса. В Java локальные переменные не могут быть объявлены статическими (static).
Методы static
Ключевое слово static используется для создания методов, которые будут существовать независимо от каких-либо экземпляров, созданных для класса.
В Java статические методы или методы static не используют какие-либо переменные экземпляра любого объекта класса, они определены. Методы static принимают все данные из параметров и что-то из этих параметров вычисляется без ссылки на переменные.
Переменные и методы класса могут быть доступны с использованием имени класса, за которым следует точка и имя переменной или метода.
Модификатор static в Java используется для создания методов классов и переменных, как показано в следующем примере:
Будет получен следующий результат:
Модификатор final
Модификатор final — используется для завершения реализации классов, методов и переменных.
Переменные final
Переменная final может быть инициализирована только один раз. Ссылочная переменная, объявленная как final, никогда не может быть назначен для обозначения другого объекта.
Однако данные внутри объекта могут быть изменены. Таким образом, состояние объекта может быть изменено, но не ссылки.
С переменными в Java модификатор final часто используется со static, чтобы сделать константой переменную класса:
Методы final
Метод final не может быть переопределен любым подклассом. Как упоминалось ранее, в Java модификатор final предотвращает метод от изменений в подклассе.
Главным намерение метода final то, что содержание метода не должно быть изменено сторонне.
Объявление метода, использующего модификатор final в объявление класса, показано в следующем примере:
Класс final
Основная цель в Java использования класса объявленного в качестве final заключается в предотвращении класс от быть подклассом. Если класс помечается как final, то ни один класс не может наследовать любую функцию из класса final.
Модификатор abstract
Модификатор abstract — используется для создания абстрактных классов и методов.
Класс abstract
Класс abstract не может создать экземпляр. Если класс объявлен как abstract, то единственная цель для него быть расширенным.
Класс не может быть одновременно abstract и final, так как класс final не может быть расширенным. Если класс содержит абстрактные методы, то он должен быть объявлен как abstract. В противном случае будет сгенерирована ошибка компиляции.
Класс abstract может содержать как абстрактные методы, а также и обычные.
Метод abstract
Метод abstract является методом, объявленным с любой реализацией. Тело метода (реализация) обеспечивается подклассом. Методы abstract никогда не могут быть final или strict.
Любой класс, который расширяет абстрактный класс должен реализовать все абстрактные методы суперкласса, если подкласс не является абстрактным классом.
Если класс в Java содержит один или несколько абстрактных методов, то класс должен быть объявлен как abstract. Абстрактный класс не обязан содержать абстрактные методы.
Абстрактный метод заканчивается точкой с запятой. Пример: public abstract sample();
Модификатор synchronized
Модификатор synchronized — используются в Java для потоков.
Ключевое слово synchronized используется для указания того, что метод может быть доступен только одним потоком одновременно. В Java модификатор synchronized может быть применен с любым из четырех модификаторов уровня доступа.
Модификатор transient
Переменная экземпляра отмеченная как transient указывает виртуальной машине Java (JVM), чтобы пропустить определённую переменную при сериализации объекта, содержащего её.
Этот модификатор включён в оператор, что создает переменную, предшествующего класса или типа данных переменной.
Модификатор volatile
Модификатор volatile — используются в Java для потоков.
В Java модификатор volatile используется, чтобы позволить знать JVM, что поток доступа к переменной всегда должен объединять свою собственную копию переменной с главной копией в памяти.
Доступ к переменной volatile синхронизирует все кэшированные скопированные переменные в оперативной памяти. Volatile может быть применен только к переменным экземпляра, которые имеют тип объект или private. Ссылка на объект volatile может быть null.
Как правило, run() вызывается в одном потоке (впервые начинаете использовать Runnable в Java), а stop() вызывается из другого потока. Если в линии один используется кэшированное значение active, то цикл не может остановиться, пока вы не установите active false в линии два.
В следующем уроке обсудим основные операторы, используемые в языке Java. Этот раздел даст вам обзор того, как можно использовать их во время разработки приложения.
Инкапсуляция
1. Введение
В чем же преимущества инкапсуляции? Их достаточно много, но я могу выделить четыре, на мой взгляд, основных:
2. Валидное внутреннее состояние
В програмах часто возникают ситуации, когда несколько классов взаимодействуют с одним и тем же объектом. В результате их совместной работы нарушается целостность данных внутри объекта – он уже не может продолжать нормально работать.
Поэтому объект должен следить за изменениями своих внутренних данных, а еще лучше — проводить их сам.
Если мы не хотим, чтобы какая-то переменная класса менялась другими классами, мы объявляем ее private, и тогда только методы её же класса смогут получить к ней доступ. Если мы хотим, чтобы значения переменных можно было только читать, но не изменять, тогда нужно добавить public getter для нужных переменных.
Правильное использование инкапсуляции гарантирует, что ни один класс не может получить прямой доступ к внутренним данным нашего класса и, следовательно, изменить их без контроля с нашей стороны. Только через вызов методов того же класса, что и изменяемые переменные.
Лучше исходить из того, что другие программисты всегда будут использовать ваши классы самым удобным для них образом, а не самым безопасным для вас (для вашего класса). Отсюда и ошибки, и попытки заранее избавиться от них.
3. Контроль передаваемых аргументов
Иногда нужно контролировать аргументы, передаваемые в методы нашего класса. Например, наш класс описывает объект «человек» и позволяет задать дату его рождения. Мы должны проверять все передаваемые данные на их соответствие логике программы и логике нашего класса. Например, не допускать 13-й месяц, дату рождения 30 февраля и так далее.
Зачем же кому-то указывать в дате рождения 30 февраля? Во-первых, это может быть ошибка ввода данных от пользователя. Во-вторых, прежде чем программа будет работать как часы, в ней будет много ошибок. Например, возможна такая ситуация.
Программист пишет программу, которая определяет людей, у которых день рождения послезавтра. Например, сегодня 3 марта. Программа добавляет к текущему дню месяца число 2 и ищет всех, кто родился 5 марта. Вроде бы всё верно.
Вот только когда наступит 30 марта, программа не найдет никого, т.к. в календаре нет 32 марта. В программе становится гораздо меньше ошибок, когда в методы добавляют проверку переданных данных.
Помните, когда мы изучали ArrayList и разбирали его код, и там была проверка индекса в методах get и set : index больше или равен нулю и меньше длины массива. Там еще выбрасывалось исключение, если в массиве нет элемента с таким индексом. Это классический пример проверки входных данных.
4. Минимизация ошибок при изменении кода классов
Представим, что мы написали один очень полезный класс, когда участвовали в большом проекте. Он так всем понравился, что другие программисты начали использовать его в сотнях мест в своем коде.
Класс оказался настолько полезен, что вы решили его улучшить. Но если вы удалите какие-то методы этого класса, код десятков людей перестанет компилироваться. Им придется срочно все переделывать. И чем больше переделок, тем больше ошибок. Вы поломаете кучу сборок, и вас будут ненавидеть.
А когда мы меняем методы, объявленные как private, мы знаем, что нигде нет ни одного класса, который вызывал бы эти методы. Мы можем их переделать, поменять количество параметров и их типы, и зависимый код будет работать дальше. Ну или как минимум компилироваться.
5. Задаем способ взаимодействия нашего объекта со сторонними объектами
Мы можем ограничить некоторые действия, допустимые с нашим объектом. Например, мы хотим, чтобы объект можно было создать только в одном экземпляре. Даже если его создание происходит в нескольких местах проекта одновременно. И мы можем сделать это благодаря инкапсуляции.
Что такое инкапсуляция в Java?
Инкапсуляция в Java – это принцип объединения данных (переменных) и кода в единое целое. Это одна из четырех концепций ООП. Другие три – это Наследование, Полиморфизм и Абстракция.
Инкапсуляция на примере
Чтобы понять, что такое инкапсуляция, рассмотрим следующий класс банковских счетов с методами депозита и отображения баланса.
Обычно переменные в классе устанавливаются как «частные», как показано ниже. Доступ к нему можно получить только с помощью методов, определенных в классе. Никакой другой класс или объект не может получить к ним доступ.
Если элемент данных является закрытым, это означает, что доступ к нему возможен только в пределах одного класса. Никакой внешний класс не может получить доступ к частному члену данных или переменной другого класса.
Но реализация метода имеет проверку на отрицательные значения. Таким образом, второй подход также терпит неудачу.
Таким образом, вы никогда не подвергаете свои данные внешней стороне. Что делает ваше приложение безопасным.
Весь код можно представить как капсулу, и вы можете общаться только через сообщения. Отсюда и название инкапсуляции.
Сокрытие данных в Java
Часто инкапсуляция Java называется скрытием данных. Но концепция инкапсуляции не просто скрывает данные, она предназначена для лучшего управления или группировки связанных данных.
Чтобы добиться меньшей степени инкапсуляции в Java, вы можете использовать такие модификаторы, как «protected» или «public». Благодаря инкапсуляции разработчики могут легко изменять одну часть кода, не затрагивая другую.
Методы получения и установки в Java
Если элемент данных объявлен как «закрытый», то доступ к нему возможен только в пределах одного класса. Никакой внешний класс не может получить доступ к данным члена этого класса. Если вам нужен доступ к этим переменным, вы должны использовать публичные методы «getter» и «setter».
Методы Getter и Setter используются для создания, изменения, удаления и просмотра значений переменных.
Следующий код является примером методов получения и установки:
В приведенном выше примере метод getBalance() – это метод получения, который считывает значение переменной account_balance, а метод setNumber() – это метод установки, который устанавливает или обновляет значение для переменной account_number.
Абстракция и Инкапсуляция – разница
Часто инкапсуляция неправильно понимается как абстракция. Давай учиться-
Простым примером, чтобы понять эту разницу, является мобильный телефон. Где сложная логика в печатной плате инкапсулирована в сенсорном экране, и интерфейс предоставлен, чтобы абстрагировать ее.
Инкапсуляция
В чем же преимущества инкапсуляции? Их достаточно много, но я могу выделить четыре, на мой взгляд, основных:
1) Валидное внутреннее состояние.
В программах часто возникают ситуации, когда несколько классов, взаимодействуют с одним и тем же объектом. В результате их совместной работы нарушается целостность данных внутри объекта — объект уже не может продолжить нормально работать.
Поэтому объект должен следить за изменениями своих внутренних данных, а еще лучше – проводить их сам.
Если мы не хотим, чтобы какая-то переменная класса менялась другими классами, мы объявляем ее private, и тогда только методы её же класса смогут получить к ней доступ. Если мы хотим, чтобы значения переменных можно было только читать, но не изменять, тогда нужно добавить public getter для нужных переменных.
Например, мы хотим, чтобы все могли узнать количество элементов в нашей коллекции, но никто не мог его поменять без нашего разрешения. Тогда мы объявляем переменную private int count и метод public getCount().
Правильное использование инкапсуляции гарантирует, что ни один класс не может получить прямой доступ к внутренним данным нашего класса и, следовательно, изменить их без контроля с нашей стороны. Только через вызов методов того же класса, что и изменяемые переменные.
Лучше исходить из того, что другие программисты всегда будут использовать твои классы самым удобным для них образом, а не самым безопасным для тебя (для твоего класса). Отсюда и ошибки, и попытки заранее избавиться от них.
2) Контроль передаваемых аргументов.
Иногда нужно контролировать аргументы, передаваемые в методы нашего класса. Например, наш класс описывает объект «человек» и позволяет задать дату его рождения. Мы должны проверять все передаваемые данные на их соответствие логике программы и логике нашего класса. Например, не допускать 13-й месяц, дату рождения 30 февраля и так далее.
— А зачем кому-то указывать в дате рождения 30 февраля?
— Во-первых – это может быть ошибка ввода данных от пользователя.
Во-вторых, прежде чем программа будет работать как часы, в ней будет много ошибок. Например, возможна такая ситуация.
Программист пишет программу для определения людей, у которых день рождения послезавтра. Например, сегодня 3 марта. Программа добавляет к текущему дню месяца число 2 и ищет всех, кто родился 5 марта. Вроде бы все верно.
Вот только, когда наступит 30 марта программа не найдет никого, т.к. в календаре нет 32 марта. В программе становится гораздо меньше ошибок, когда в методы добавляют проверку переданных данных.
— Помню, когда мы изучали ArrayList, я смотрел его код, и там была проверка индекса в методах get и set: index больше или равен нулю и меньше длины массива. Там еще кидалось исключение, если в массиве нет элемента с таким индексом.
— Да, это классический пример проверки входных данных.
3) Минимизация ошибок при изменении кода классов.
Представим, что мы написали один очень полезный класс, когда участвовали в большом проекте. Он так всем понравился, что другие программисты начали использовать его в сотнях мест в своем коде.
Класс оказался настолько полезен, что ты решил его улучшить. Но если ты удалишь какие-то методы этого класса, то код десятков людей перестанет компилироваться. Им придется срочно все переделывать. И чем больше переделок, тем больше ошибок. Ты поломаешь кучу сборок, и тебя будут ненавидеть.
А когда мы меняем методы, объявленные как private, мы знаем, что нигде нет ни одного класса, который вызывал бы эти методы. Мы можем их переделать, поменять количество параметров и их типы, и зависимый код будет работать дальше. Ну, или как минимум, компилироваться.
4) Задаем способ взаимодействия нашего объекта со сторонними объектами.
Мы можем ограничить некоторые действия, допустимые с нашим объектом. Например, мы хотим, чтобы объект можно было создать только в одном экземпляре. Даже если его создание происходит в нескольких местах проекта одновременно. И мы можем сделать это благодаря инкапсуляции.