Как именовать пакеты в java
Пакеты Java – назначение и использование
Пакеты Java – это механизм для группировки классов, которые связаны друг с другом, в одну и ту же «группу» (пакет). Когда проект становится больше, например, приложение или API, полезно разделить код на несколько классов, а классы – на несколько пакетов. Тогда становится легче выяснить, где находится определенный класс, который вы ищете.
Пакет подобен каталогу в файловой системе. На самом деле на диске он является каталогом. Все исходные файлы и файлы классов, принадлежащих одному и тому же пакету, находятся в одном каталоге.
Могут содержать подпакеты. Таким образом, могут составлять так называемую структуру пакета, похожую на структуру каталогов. Это дерево пакетов, подпакетов и классов внутри этих классов. Организована как каталоги на вашем жестком диске или как каталоги внутри zip-файла (JAR-файлы).
Вот скриншот примера структуры:
Вверху вы видите каталог с именем “src”. Это исходный корневой каталог. Это не сам пакет. Внутри этого каталога все подкаталоги соответствуют пакетам. Таким образом, «коллекции», «com», «параллелизм» и т. д. – это все пакеты (которые также являются каталогами на диске). На снимке экрана выше они показаны значком папки.
Расширено два пакета подуровня, чтобы вы могли видеть классы внутри. Классы проиллюстрированы с помощью маленького синего круга с буквой C внутри, на скриншоте выше.
Полный путь к подпакету – это его имя со всеми именами пакетов-предков, разделенных точками. Например, полный путь к «навигационному» подпакету:
Точно так же полное имя класса включает имя его пакета. Например, полное имя класса «Page»:
Создание структуры
Чтобы создать пакет, вы должны сначала создать корневой каталог на вашем жестком диске. Он сам по себе не является частью структуры пакета. Содержит все исходные коды, которые должны войти в структуру.
Создав исходный корневой каталог, вы можете начать добавлять в него подкаталоги. Каждый подкаталог соответствует пакету. Вы можете добавить подкаталоги в подкаталоги, чтобы создать более глубокую структуру.
Добавление классов
Чтобы добавить классы, вы должны сделать две вещи:
Первый пункт довольно прост. Создайте корневой каталог источника и внутри него создайте каталоги для каждого пакета и подпакета рекурсивно. Поместите файлы классов в каталог, соответствующий пакету, в который вы хотите добавить его.
Когда вы поместили свой исходный файл в правильный каталог (соответствующий пакету, к которому должен принадлежать класс), вы должны объявить внутри этого файла класса, что он принадлежит этому пакету:
Первая строка в приведенном выше коде – это то, что объявляет класс Page принадлежащим к com.blog.navigation.
Соглашения об именах
Пакеты всегда пишутся строчными буквами. В отличие от классов, где первая буква обычно является заглавной.
Чтобы избежать создания пакетов с такими же именами, как у других общедоступных, рекомендуется начинать иерархию с обратного доменного имени вашей компании. Например, поскольку доменное имя компании – blog.com, надо начать со структуры с именем com.blog. Другими словами, пакет верхнего уровня с именем com с подпакетом внутри называется blog.
Импорт
Если класс A должен использовать класс B, вы должны ссылаться на класс B внутри класса A. Если классы A и B находятся в одном и том же пакете, компилятор будет принимать ссылки между двумя классами:
Если классы A и B находятся в одном и том же пакете, проблем с кодом выше нет. Однако, если класс A и B находятся в разных, класс A должен импортировать класс B, чтобы использовать его:
Это первая строка в примере, которая импортирует класс B. В примере предполагается, что класс B находится в пакете с именем anotherpackage.
Если бы класс B находился в подпакете другого пакета, вам пришлось бы перечислить полный путь пакета и подпакета к классу B. Например, если бы класс B находился в пакете anotherpackage.util, то оператор import выглядел бы так:
Импорт всех классов из другого пакета
Если вам нужно использовать много классов из определенного пакета, их импорт по одному приводит к большому количеству операторов импорта. Можно импортировать все классы, используя символ * вместо имени класса:
Использование классов через определенное имя
Можно использовать класс из другого пакета, не импортируя его с помощью оператора импорта. Вы можете написать полное имя его, а не просто имя самого класса. Полное имя класса состоит из полного пути пакета до подкласса, содержащего класс, а также самого имени класса. Полное имя класса – это то, что вы написали бы в операторе импорта. Например:
Вы можете использовать это полное имя класса для ссылки на класс TimeUtil внутри другого класса, например так:
Пакетное разделение
Официального стандарта для этого нет, но есть два широко используемых метода.
Разделить на слои
Первый метод состоит в том, чтобы разделить классы после определения, к какому «слою» приложения они принадлежат. Например, ваше приложение может иметь слой базы данных. Тогда вы создадите пакет базы данных. Все классы, участвующие в обмене данными с базой данных, будут расположены в нем.
Разделить по функциональности приложения
Второй метод – разделить ваши классы в зависимости от того, к какой части функциональности приложения они принадлежат. Таким образом, если ваше приложение имеет функциональную область, которая рассчитывает пенсии, вы можете создать пакет с именем pension. Все классы, так или иначе участвующие в пенсионных расчетах, будут включены в него (или подпакеты, если число классов в пенсии станет большим).
В сочетании с доменным именем структура для пенсионного пакета будет:
Всего три пакета, два вложенных в другие.
Метод «деления по функциональности приложения» имеет тенденцию работать лучше, чем «деление по слоям», поскольку в вашем приложении растет число классов.
Вместо того, чтобы иметь фиксированное количество пакетов слоев, число которых продолжает расти, вы получаете растущее число пакетов функциональности приложения с меньшим количеством классов внутри.
Встроенные
Платформа поставляется с множеством встроенных пакетов. Они содержат классы для самых разных целей, которые часто нужны программистам, например, чтение и запись файлов с локального жесткого диска, отправка и получение данных по сетям и Интернету, подключение к базам данных и многое, многое другое.
Пакеты (packages)
— Привет, Амиго! Сегодня я расскажу тебе про пакеты.
— Файлы в компьютере группируются по папкам. Классы в Java (а каждый класс лежит в отдельном файле) группируются по пакетам, которые являются папками на диске. Ничего принципиально нового. Но есть два замечания
— Первое. «Полным уникальным именем класса» является «имя пакета» + «имя класса». Примеры:
Полное уникальное имя | Имя пакета | Имя класса |
---|---|---|
java.io.FileInputStream | java.io | FileInputStream |
java.lang.String | java.lang | String |
java.util.ArrayList | java.util | ArrayList |
org.apache.tomcat.Servlet | org.apache.tomcat | Servlet |
Cat | отсутствует | Cat |
— Полное имя класса всегда уникально!
— Каждый раз писать длинное имя, например java.util.ArrayList, очень неудобно. Поэтому в Java добавили возможность «импортировать классы». В своем коде ты можешь пользоваться коротким именем других классов, но ты должен в начале своего класса явно указать, какой именно класс будет использоваться.
— Делается это конструкцией вида « import java.util.ArrayList; »
— В начале класса, сразу после объявления package, ты можешь указать какой именно класс скрывается за ArrayList, который ты используешь у себя в коде.
— Зачем такая сложность? Что могут быть классы с одинаковыми именами?
— Вот еще одна аналогия. У тебя в коллективе есть Серега и никаких проблем с общением – все знают кто это. Но если бы их было трое, то чтобы их различать пришлось бы использовать полные уникальные имена.
В Java принято давать классам и пакетам осмысленные имена. Многие компании выпускают свои библиотеки (набор классов) и, чтобы не было путаницы, называют пакеты этих классов по имени компании/сайта:
28. Java – Пакеты
В Java пакеты (package) используются для предотвращения конфликтов с названиями, для контроля доступа, для облегчения поиска/нахождения и использования классов, интерфейсов, перечислений и аннотаций и т.д.
Пакеты можно определить как группировку связанных типов (классы, интерфейсы, перечисления и аннотации), предоставляющий защиту доступа и управление пространством имён.
Содержание
Некоторые из существующих пакетов в Java:
Программисты могут определять их пакеты для связывания групп классов/интерфейсов и т.д. Группировка связанных классов, реализованных вами, является хорошим практическим решением, т.к. программист сможет легко определить, что классы, интерфейсы, перечисления и аннотации связаны.
Так как пакет создаёт новое пространство имён, в нём не будет никаких конфликтов с именами в других пактах. Используя пакеты, легче предоставить управление доступом и легче найти связанные классы.
Создание пакета
Как создать пакет в Java? Во время создания пакета вы должны выбрать ему имя и включить оператор package вместе с этим именем поверх каждого исходного файла, который содержит классы, интерфейсы, перечисления и типы аннотаций, которые вы хотите включить в пакет.
Оператор package должен быть первой строкой в исходном файле. Может быть только один запрос package в каждом исходном файле, и он применяется ко всем типам в этом файле.
Если оператор package не использован, тогда классы, интерфейсы, перечисления и типы аннотаций будут помещены в текущий пакет по умолчанию.
Чтобы скомпилировать программы на Java с операторами package, то вам нужно использовать опцию –d, как показано ниже.
Затем в указанном месте назначения создается папка с указанным именем пакета, а файлы скомпилированных классов будут помещены в эту папку.
Пример 1
Давайте взглянем на пример, которые создаёт пакет под названием animals. Полезно использовать имена пакетов с маленькой буквы, чтобы избежать конфликтов с именами классов и интерфейсов.
В следующем примере пакета содержится интерфейс с названием animals.
Теперь давайте реализуем вышеприведённый интерфейс в этом же пакете animals:
А сейчас скомпилируем java-файлы, как показано ниже:
Теперь пакет/папка с именем animals будет создана в текущей директории, и файлы классов будут помещены в неё.
Вы можете запустить файл класса внутри пакета и получить результат, указанный ниже.
Ключевое слово import
Если класс хочет использовать другой класс в том же пакете, то не нужно использовать имя пакета. Классы в одном пакете могут найти друг друга без особого синтаксиса.
Пример 2
Итак, класс под названием Boss добавлен в пакет payroll, который уже содержит Employee. Boss может обратиться к классу Employee без использования префикса payroll, как показано в следующем классе Boss.
Что произойдёт, если класс Employee не будет включен в пакет payroll? Тогда класс Boss должен будет использовать одну из следующих техник для обращения к классу в другом пакете:
Примечание: Файл класса может содержать любое количество операторов импорта (import). Операторы импорта (import) должны появляться после оператора пакета (package) и перед объявлением класса.
Структура директории пакетов
Происходят два явления, когда класс помещён в пакет:
Есть лёгкий способ работы с вашими файлами в Java:
Теперь поместите исходный файл в директорию, имя которой отражает имя пакета, к которому принадлежит класс:
Полноценное имя класса и пути будет выглядеть так:
В общем, компания использует своё обратное доменное имя в Интернете для своих именований пакетов в Java.
Например: доменное имя компании называется apple.com, тогда все имена их пакетов будут начинаться с com.apple. Каждый компонент имени пакета соответствует поддиректории.
Например: у компании есть пакет com.apple.computers, в котором содержится исходный файл Dell.java, тогда он содержится в серии поддиректорий, как указано здесь:
Теперь скомпилируйте это, используя опцию –d:
Файлы скомпилируются следующим образом:
Вы можете импортировать все классы и интерфейсы, определённые в \com\apple\computers\ вот так:
Делая так, становится возможным предоставить доступ к директории классов другим программистам, не раскрывая ваши источники. Вам также нужно распределить файлы классов и источников таким образом, чтобы компилятор и Java Virtual Machine (JVM) могли найти все типы, которые использует ваша программа.
Полный путь к директории классов
Путь класса может включать несколько путей. Множество путей должны быть отделены точкой с запятой (Windows) или двоеточием (Unix). По умолчанию компилятор и JVM ищут текущую директорию и JAR-файл, содержащий классы платформы Java, чтобы эти директории были автоматически включены в путь класса.
Установить системную переменную CLASSPATH
Чтобы отобразить текущую CLASSPATH переменную, используйте следующие команды в Windows и UNIX (Bourne shell):
Чтобы удалить содержимое переменной CLASSPATH, используйте:
Чтобы установить системную переменную CLASSPATH:
Проекты в Java
1. Пакеты
В стандартных Java-программах очень много классов. Сколько? Тысячи, десятки тысяч. А если еще посчитать, что программа использует различные библиотеки, которые содержат классы, написанные другими программистами, то количество классов легко может исчисляться миллионами!
Для всех этих миллионов, да и просто тысяч классов невозможно придумать уникальные имена.
Поэтому в Java все классы сгруппированы по пакетам.
Классы и их пакеты в Java по своей сути очень напоминают файлы и папки на компьютере.
Например, если вам нужно хранить на компьютере 10 документов, вы скорее всего просто будете хранить их в одной папке. А если документов тысячи (например, хранилище всех документов компании)?
Если бы нужно было хранить тысячи документов, решением было бы разработать несколько уровней папок с хорошими говорящими названиями. И в папке самого последнего уровня хранить документы, которые относятся к этой конкретной папке. Хорошие говорящие названия для документов тоже не помешают.
Фактически в Java это все и было сделано для классов.
Файлы с классами хранятся в разных директориях (папках), и полное название папки класса со всеми подпапками называется пакетом класса. Пример:
Путь к файлу | Имя пакета | Имя класса |
---|
2. Папка src
В Java принято все классы одной программы хранить в одной папке (и ее подпапках). Такую папку обычно называют src (сокращение от source ).
Такая папка называется корнем проекта ( source root ), и все пути для пакетов считаются от нее. Примеры:
В Java принято давать классам и пакетам осмысленные имена. Многие компании выпускают свои библиотеки (набор классов) и, чтобы не было путаницы, называют пакеты этих классов по имени компании/сайта/проекта:
Имя пакета | Имя компании/проекта |
---|---|
Проект «Apache» | |
Компания «Oracle» | |
Компания Oracle, проект Java | |
Компания «IBM», проект WebSphere | |
Проект «Jboss» |
3. Содержимое файла
Согласно стандарту языка Java, внутри файла с кодом должна быть записана информация об имени класса и имя его пакета. Схема стандарта приведена ниже:
Имя пакета должно совпадать с именем папки, а имя файла — с именем публичного класса.
4. Импорт классов
Полное уникальное имя | Имя пакета | Имя класса |
---|---|---|
отсутствует |
Хорошая новость:
Полное имя класса всегда уникально в рамках одного проекта. Ну вы же не можете создать два файла с одним и тем же именем в одной и той же папке.
Плохая новость:
Полные имена классов обычно либо длинные, либо очень длинные. А ведь каждый раз писать в коде длинное имя, например java.util.ArrayList, очень неудобно.
Поэтому в Java добавили возможность «импортировать классы».
Чтобы использовать короткое имя класса в своем коде, вам нужно добавить вот такую конструкцию в свой код:
А вот как бы выглядел этот же код, если бы мы не использовали import :
Допустим, у вас в коллективе есть Серега, и никаких проблем с общением, не возникает — все знают кто это. Но если бы их было трое, чтобы их различать, пришлось бы использовать полные уникальные имена.
Кстати, если вам лень добавлять много импортов в ваш класс, вы можете воспользоваться его версией для ленивых: вместо имени класса поставить звездочку:
Таким образом, вы сможете использовать в вашем коде короткие имена всех классов из данного пакета.
Pro Java
Страницы
30 июн. 2015 г.
Пакеты в Java.
Пакет (package) представляет собой именованную совокупность классов (и, возможно, подпакетов). Пакеты группируют классы и определяют пространства имен для классов, которые в них входят.
Зачем нужны пакеты в Java и что это такое
Платформа Java содержит пакеты, имена которых начинаются на com, java, javax и org. Посмотрите это в сырцах, не поленитесь. Основные классы языка входят в пакет java.lang. Различные вспомогательные классы находятся в java.util. Классы для ввода и вывода входят в java.io, а классы для работы в сети – в java.net. Некоторые их этих пакетов содержат подпакеты. Например, java.lang содержит два специализированных пакета java.lang.reflect и java.lang.ref, а java.util содержит подпакет java.util.zip, который в свою очередь содержит классы для работы с ZIPархивами.
Каждый класс имеет как простое имя, данное ему в определении, так и полное имя, включающее имя пакета, в который он входит. Например, класс String является частью пакета java.lang, а его полное имя – java.lang.String.
В стандартную библиотеку Java API входят сотни классов. Каждый программист в ходе работы добавляет к ним десятки своих классов. Множество классов растет и становится необозримым. Уже давно принято отдельные классы, решающие какую-то одну определенную задачу, объединять в библиотеки классов. Но библиотеки классов, кроме стандартной библиотеки, не являются частью языка.
Разработчики Java включили в язык дополнительную конструкцию — пакеты (packages). Все классы Java распределяются по пакетам. Кроме классов пакеты могут содержать интерфейсы и вложенные подпакеты (subpackages). Образуется древовидная структура пакетов и подпакетов.
Эта структура в точности отображается на структуру файловой системы. Все файлы с расширением class (содержащие байт-коды), образующие один пакет, хранятся в одном каталоге файловой системы. Подпакеты образуют подкаталоги этого каталога.
Каждый пакет создает одно пространство имен (namespace). Это означает, что все имена классов, интерфейсов и подпакетов в пакете должны быть уникальны. Имена в разных пакетах могут совпадать, но это будут разные программные единицы. Таким образом, ни один класс, интерфейс или подпакет не может оказаться сразу в двух пакетах. Если надо в одном месте программы использовать два класса с одинаковыми именами из разных пакетов, то имя класса уточняется именем пакета: пакет.Класс. Такое уточненное имя называется полным именем класса (fully qualified name).
Все эти правила, опять-таки, совпадают с правилами хранения файлов и подкаталогов в каталогах, только в файловых системах для разделения имен каталогов в пути к файлу обычно используется наклонная черта или двоеточие, а не точка.
Определение пакета
Поскольку строка package имя; только одна и это обязательно первая строка файла, каждый класс попадает только в один пакет или подпакет.
До сих пор мы создавали классы без директивы package. Классы, определяемые файлом Java-кода без директивы package, входят в пакет без имени, существующий по умолчанию. Как вы узнаете чуть позже, классы одного пакета получают специальный доступ друг к другу. Именно поэтому, когда мы использовали в программе несколько классов, мы могли получать доступ из одного класса к методам или полям другого.
Компилятор всегда создает для таких классов безымянный пакет (unnamed package), которому соответствует текущий каталог (current working directory) файловой системы.
Поэтому, если только вы не пишете простые или учебные программы, всегда используйте директиву package, чтобы закрыть доступ в ваши классы из совершенно посторонних классов. Безымянный пакет служит обычно хранилищем небольших пробных или промежуточных классов. Большие проекты лучше хранить в пакетах. Более того, некоторые программные продукты Java вообще не работают с безымянным пакетом. Поэтому в технологии Java рекомендуется все классы помещать в пакеты.
Одной из важных функций пакетов является разделение пространства имен Java и предотвращение конфликта имен между классами. Например, классы java.util.List и java.awt.List можно различить только по именам их пакетов. Однако важно, чтобы различались и имена самих пакетов.
Как работают пакеты
Использование класса из пакета:
Методы и поля классов в текущем пакете доступны другим классам из этого же пакета, если у них нет ни каких модификаторов доступа (о которых мы поговорим чуть позже).
А вот классы и их поля и методы принадлежащих другим пакетам, если у них нет ни каких модификаторов доступа, уже не доступны даже по полному имени пакета и класса.
Чтобы отдохнуть от теории и понять ее получше немного попрактикуемся и рассмотрим на примере первый пункт использование класса из пакета. Создадим пакет pro.java.pkg001 и в нем два класса:
Вывод у программы следующий:
Как видно у класса Print нет ни каких модификаторов, но все же его статические метод и переменная видны из класса Main и могут им использоваться.
Импорт классов и пакетов
Класс пакета pro.java.pkg001 может ссылаться на любой другой класс в pro.java.pkg001 по его простому имени. А поскольку классы пакета java.lang являются базовыми для языка Java, любой Java-код может ссылаться на любой класс этого пакета по его простому имени. Значит, всегда можно набирать String вместо java.lang.String. Однако по умолчанию для всех других классов нужно указывать полные имена. Поэтому, чтобы применить класс File пакета java.io, следует набрать java.io.File.
Директива import бывает двух видов. Чтобы определить отдельный класс, на который можно ссылаться по его простому имени, следом за ключевым словом import введите имя класса и точку с запятой:
import java.io.File; // Теперь можно набирать File вместо java.io.File
import java.io.*; // Теперь простые имена можно применять для всех классов из java.io
Начиная с версии Java 5 в язык введена еще одна форма оператора import, предназначенная для импорта статических полей и методов класса — оператор import static. Например, можно написать оператор:
import static java.lang.Math.*;
После этого все статические поля и методы класса Math можно использовать без указания имени класса. Вместо записи:
можно записать просто
Теперь разгаданы и другие строчки, которые были в наших исходниках, например:
import static pro.java.util.Print.*;
import static pro.java.util.Strings.*;
Подчеркнем, что оператор import вводится только для удобства программистов и слово «импортировать» не означает никаких перемещений классов.
Структура файла Java
Теперь можно описать структуру исходного файла с текстом программы на языке Java.
Данные элементы могут перемежаться с комментариями, но они должны идти именно в такой последовательности.
Директив import может быть сколько угодно.
Отсюда следует, что если в проекте есть несколько открытых классов, то они должны находиться в разных файлах.
Соглашение «Code Conventions» рекомендует открытый класс, если он имеется в файле, описывать первым.
Даже если ваши классы не являются public, полезно определять только по одному классу на файл и давать файлу имя класса. Для технологии Java характерно записывать исходный текст каждого класса в отдельном файле. В конце концов, компилятор всегда создает class-файл для каждого класса.
Исполнение классов в пакетах и CLASSPATH
С запуском нашей простой программы из Eclipse, что была в самом начале, нет ни каких проблем, а вот при запуске из командной строки они могут возникнуть.
Дело в том, что как я уже говорил ранее, в откомпилированный class файл попадает полное имя класса, то есть имя_пакета.имя_класса.
Давайте запустим и посмотрим (обращаем внимание на пути файлов):
Мы попробовали запустить наш класс Main способом как мы делали и раньше, находясь в каталоге с классом. Но вдруг, внезапно, выдалась ошибка, что не возможно найти метод main в классе Main.
javap спасет отца русской демократии! Давайте посмотрим что там у нас скомпилилось?
Как видим наш класс сейчас называется pro.java.pkg001.Main, то есть наш класс содержит полное имя, включая имя пакета. И кстати обратите внимание на то как объявлен массив String[].
Для контраста рассмотрим любой класс, где мы не использовали пакеты.
Рассмотрим откомпилированный класс Classes001.
Как видим в данном случае, когда мы не использовали пакеты, имя класса точно такое же как мы и задавали в коде программы. Именно поэтому мы могли запустить наш класс по его короткому имени.
Давайте попробуем запустить наш класс Main по полному имени и посмотрим что получиться.
Как видим у нас опять ошибка.
Чтобы наша программа запустилась, должно выполняться одно из следующих двух условий. Либо программа должна выполняться из каталога, расположенного непосредственно над каталогом pro, то есть в нашем случае запуск должен происходить из каталога bin, либо переменная среды CLASSPATH должна содержать путь к каталогу pro, либо параметр –classpath должен указывать путь к каталогу pro во время выполнения программы с помощью java.
CLASSPATH должен указывать путь к каталогу, где лежит пакет (верхний каталог пакета), но не на сам каталог или подкаталоги пакета.
Ну и на последок можно глянуть хорошее видео по этой теме