Прежде чем приступить к изложению статьи, хочу обратить внимание на два нижеприведенных рисунка.
На одном из них код программы, точнее файлы, сваленные в одну кучу: и исходные, и скомпилированные – сам черт ногу сломит). А на другом – все разложено по полочкам (по папочкам) Теперь вопрос: где нам лучше ориентироваться в программном коде среди файлов? Ответ очевиден. Поэтому с моей точки зрения, пакеты в java ДЛЯ НАЧИНАЮЩЕГО программиста являются средством удобной навигации среди файлов программы, и только потом – для ПРЕДОТВРАЩЕНИЯ ГЛОБАЛЬНОГО КОНФЛИКТА ИМЕН. Это справедливо, ведь на начальном этапе начинающий программист создает небольшие программы, которые, в общем, должны использоваться для своего саморазвития. И вероятность того, что в программе встретятся классы с одинаковыми именами, ничтожна мала. Хотя и разобраться с пакетами java для новичка, скажем, задача не простая. Поэтому, чтобы в полной мере понять смысл пакетов, не нужно пользоваться разными IDE, а на начальном этапе работать «ручками», т.е. с помощью «командной строки». ...javac, java, ну, вообщем, меня поняли).
Итак, как создать пакет в java? Организация пакетов в java осуществляется с помощью ключевого слова package и записывается первой строкой. Иерархия вложенных пакетов создается с помощью точки «.», например, package givotnie.mlekopitajugie.kochagi, что должно быть соответствовать СТРОГО вложениям нашим «папочкам» на нашем девайсе. Ну как-то так:
Обратите внимание на то, в какой директории файловой системе нужно находиться, чтобы скомпилировать и запускать программу в командной строке.
Далее, чтобы в нашей программе использовать классы (создавать объекты, наследовать), принадлежащие определенному пакету, их нужно импортировать в наш код с помощью ключевого слова import.
import givotnie.mlekopitajugie.kochagi.Tigr;
в данной строке произойдет импортирование только одного класса Tigr из пакета. Но если мы собираемся использовать все классы данного пакета, то нам придётся сделать таким образом с помощью символа «*»:
import givotnie.mlekopitajugie.kochagi.*;
Однако нужно отметить, что есть альтернативный способ обращения к классам, который заключается в приведении полного имени непосредственно в коде программы:
givotnie.mlekopitajugie.Medved medved=new givotnie.mlekopitajugie.Medved("Боря");
В java import только сокращает количество дублирующего кода программы.
Теперь представим, что пишем крутое приложение с большим количеством классов, настолько большим, что совпадают случайно два одинаковых названия классов. Естественно происходит конфликт имен, так как помним, что у нас в папке, где размещен код – смешались «...кони, люди...». Однако пакеты позволяют нам избежать таких состояний, конфликтов. Смотрим:
Здесь остановимся немного подробнее. Как мы видим, в программе используются два класса с одинаковым названием Tigr, но конфликта имен не происходит, так как они находятся в разных пакетах, и поэтому у них разные полные имена:
givotnie.mlekopitajugie.kochagi.Tigr
givotnie.mlekopitajugie.Tigr
Однако на этапе компиляции программы отдается предпочтение для импорта классу, который указан явно, хотя предполагалось использовать класс, указанный в пакете givotnie.mlekopitajugie.kochagi
Попробуйте записать пакеты таким образом:
impotr givotnie.mlekopitajugie.kochagi.*;
import givotnie.mlekopitajugie.*;
и вы получите ошибку, так как компилятор не совсем понимает, какой требуется класс Tigr. И все-таки попробуем использовать в программе два одинаковых класса. Для этого нам придется указать в коде их полные имена, чтобы компилятор понимал, что к чему).
Таким образом пакеты помогают;
1. Структурировать программный код
2. Предотвратить конфликт имен. Здесь даже не в рамках одной программы и одного программиста, а приложения, которое пишут огромное количество людей. Поэтому вероятность конфликта имен здесь наиболее высока. Для этого рекомендуется в названиях пакетов использовать свое доменное имя, записанное наоборот, например:
ry.yagdmitrij
Мы уже немного касались прав доступа. Сейчас рассмотрим несколько шире, так как пакеты оказывают сильное влияние на предоставление прав. Ниже приведена табличка и разъясняющие рисунки:
Что имеем. У нас два пакета А и В. В первом находится класс А, к переменным которого мы будем пытаться получить доступ, его подкласс А1 и еще один класс А2. Во втором пакете – класс В и подкласс В1, расширяющий класс А. Т.е. мы имеем два подкласса расширяющие класс А и при этом находящиеся в разных пакетах.
Если нужно закрыть от пользователя класс, метод или переменную, всегда ставим private. Я бы сказал, вначале private, а уже потом решаем: открывать или нет. И второе: доступ по умолчанию – это доступ в пределах пакета без модификаторов, например:
(модификатора нет) class Tigr {
}
Теперь все это перенесем на структурную схему, где наши домики – это классы. Немного изменим наше представление о классах. Теперь класс – это некая фирма, где работают сотрудники (public, protected, private и «по умолчанию»). У фирмы есть филиалы (подклассы), размещенные в разных городах (пакетах). Соответственно города принадлежат к определенному району (тоже пакету). У каждого сотрудника свой кабинет, в который имеют доступ входить только определенные сотрудники. Как-то так:
…и соответственно в коде:
Еще раз обратите внимание на работу конструкторов суперкласса. Я специально ввел названия пакетов, совпадающие с названиями классов, чтобы убедиться, что конфликта нет.
Подведем итоги. Пакеты являются фундаментальной частью java, позволяющие создавать масштабируемые и поддерживаемые приложения. Правильное использование пакетов помогает организовать код и сделать его более понятным для других разработчиков. Что касается прав доступа: правильное их использование - ключевой элемент разработки качественного Java-кода. Они помогают создать надёжную архитектуру приложения и защитить данные от нежелательного доступа. При проектировании классов всегда следует тщательно продумывать уровень доступа для каждого элемента.
Следующие статьи будут посвящены нововведениям в java, а сейчас ставьте лайки и подписывайтесь на канал, чтобы не пропустить интересные статьи о java.
моя телега