В Java пакеты (package) используются для предотвращения конфликтов с названиями, для контроля доступа, для облегчения поиска/нахождения и использования классов, интерфейсов, перечислений и аннотаций и т.д.
Пакеты можно определить как группировку связанных типов (классы, интерфейсы, перечисления и аннотации), предоставляющий защиту доступа и управление пространством имён.
Некоторые из существующих пакетов в Java:
- java.lang – связывает фундаментальные классы.
- java.io – классы для ввода и выводные функции связаны в этом пакете.
Программисты могут определять их пакеты для связывания групп классов/интерфейсов и т.д. Группировка связанных классов, реализованных вами, является хорошим практическим решением, т.к. программист сможет легко определить, что классы, интерфейсы, перечисления и аннотации связаны.
Так как пакет создаёт новое пространство имён, в нём не будет никаких конфликтов с именами в других пактах. Используя пакеты, легче предоставить управление доступом и легче найти связанные классы.
Создание пакета
Как создать пакет в Java? Во время создания пакета вы должны выбрать ему имя и включить оператор package вместе с этим именем поверх каждого исходного файла, который содержит классы, интерфейсы, перечисления и типы аннотаций, которые вы хотите включить в пакет.
Оператор package должен быть первой строкой в исходном файле. Может быть только один запрос package в каждом исходном файле, и он применяется ко всем типам в этом файле.
Если оператор package не использован, тогда классы, интерфейсы, перечисления и типы аннотаций будут помещены в текущий пакет по умолчанию.
Чтобы скомпилировать программы на Java с операторами package, то вам нужно использовать опцию –d, как показано ниже.
javac -d Destination_folder file_name.java
Затем в указанном месте назначения создается папка с указанным именем пакета, а файлы скомпилированных классов будут помещены в эту папку.
Пример 1
Давайте взглянем на пример, которые создаёт пакет под названием animals. Полезно использовать имена пакетов с маленькой буквы, чтобы избежать конфликтов с именами классов и интерфейсов.
В следующем примере пакета содержится интерфейс с названием animals.
/* File name : Animal.java */
package animals;
interface Animal {
public void eat();
public void travel();
}
Теперь давайте реализуем вышеприведённый интерфейс в этом же пакете animals:
package animals;
/* File name : MammalInt.java */
public class MammalInt implements Animal {
public void eat() {
System.out.println("Млекопитающее кушает");
}
public void travel() {
System.out.println("Млекопитающее путешествует");
}
public int noOfLegs() {
return 0;
}
public static void main(String args[]) {
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
А сейчас скомпилируем java-файлы, как показано ниже:
$ javac -d . Animal.java
$ javac -d . MammalInt.java
Теперь пакет/папка с именем animals будет создана в текущей директории, и файлы классов будут помещены в неё.
Вы можете запустить файл класса внутри пакета и получить результат, указанный ниже.
Mammal eats
Mammal travels
Ключевое слово import
Если класс хочет использовать другой класс в том же пакете, то не нужно использовать имя пакета. Классы в одном пакете могут найти друг друга без особого синтаксиса.
Пример 2
Итак, класс под названием Boss добавлен в пакет payroll, который уже содержит Employee. Boss может обратиться к классу Employee без использования префикса payroll, как показано в следующем классе Boss.
package payroll;
public class Boss {
public void payEmployee(Employee e) {
e.mailCheck();
}
}
Что произойдёт, если класс Employee не будет включен в пакет payroll? Тогда класс Boss должен будет использовать одну из следующих техник для обращения к классу в другом пакете:
- Можно использовать полноценное имя класса. К примеру:
payroll.Employee
- Импорт пакета. В Java пакет может быть импортирован с помощью ключевого слова import и wild card. (*). Например:
import payroll.*;
- Сам класс можно импортировать с помощью ключевого слова import. Взглянем:
import payroll.Employee;
Примечание: Файл класса может содержать любое количество операторов импорта (import). Операторы импорта (import) должны появляться после оператора пакета (package) и перед объявлением класса.
Структура директории пакетов
Происходят два явления, когда класс помещён в пакет:
- Имя пакета в Java становится частью имени класса, как мы только что выяснили в прошлой секции.
- Имя пакета должно соответствовать со структурой директории, где находится соответствующий байт-код.
Есть лёгкий способ работы с вашими файлами в Java:
Поместите исходный код для класса, интерфейса, перечисления или типа аннотации в текстовый файл, имя которого является простым именем типа с расширением .java.
К примеру:
// File Name : Car.java
package vehicle;
public class Car {
// Class implementation.
}
Теперь поместите исходный файл в директорию, имя которой отражает имя пакета, к которому принадлежит класс:
....\vehicle\Car.java
Полноценное имя класса и пути будет выглядеть так:
- Имя класса – vehicle.Car
- Путь к файлу – vehicle\Car.java (в Windows)
В общем, компания использует своё обратное доменное имя в Интернете для своих именований пакетов в Java.
Например: доменное имя компании называется apple.com, тогда все имена их пакетов будут начинаться с com.apple. Каждый компонент имени пакета соответствует поддиректории.
Например: у компании есть пакет com.apple.computers, в котором содержится исходный файл Dell.java, тогда он содержится в серии поддиректорий, как указано здесь:
....\com\apple\computers\Dell.java
Компилятор создаёт во время компиляции другой файл вывода для каждого класса, интерфейса и перечисления, определённых в нём. Обычное имя файла вывода состоит из имени типа и расширения .class.
Например:
// File Name: Dell.java
package com.apple.computers;
public class Dell {
}
class Ups {
}
Теперь скомпилируйте это, используя опцию –d:
$javac -d . Dell.java
Файлы скомпилируются следующим образом:
.\com\apple\computers\Dell.class
.\com\apple\computers\Ups.class
Вы можете импортировать все классы и интерфейсы, определённые в \com\apple\computers\ вот так:
import com.apple.computers.*;
Как и исходные файлы .java, скомпилированные файлы .class должны быть в серии директорий, которые отражают имя пакета. Однако путь к файлам .class не должен быть таким же, как путь к исходным файлам .java. Вы можете разделить директории для классов и источников вот так:
\sources\com\apple\computers\Dell.java
\classes\com\apple\computers\Dell.class
Делая так, становится возможным предоставить доступ к директории классов другим программистам, не раскрывая ваши источники. Вам также нужно распределить файлы классов и источников таким образом, чтобы компилятор и Java Virtual Machine (JVM) могли найти все типы, которые использует ваша программа.
Полный путь к директории классов
Допустим,
Путь класса может включать несколько путей. Множество путей должны быть отделены точкой с запятой (Windows) или двоеточием (Unix). По умолчанию компилятор и JVM ищут текущую директорию и JAR-файл, содержащий классы платформы Java, чтобы эти директории были автоматически включены в путь класса.
Установить системную переменную CLASSPATH
Чтобы отобразить текущую CLASSPATH переменную, используйте следующие команды в Windows и UNIX (Bourne shell):
- Для Windows — C:\> set CLASSPATH
- Для UNIX — % echo $CLASSPATH
Чтобы удалить содержимое переменной CLASSPATH, используйте:
- Для Windows — C:\> set CLASSPATH =
- Для UNIX — % unset CLASSPATH; export CLASSPATH
Чтобы установить системную переменную CLASSPATH: