Creating a Package
To create a package, you choose a name for the package (naming conventions are discussed in the next section) and put a package statement with that name at the top of every source file that contains the types (classes, interfaces, enumerations, and annotation types) that you want to include in the package.
The package statement (for example, package graphics; ) must be the first line in the source file. There can be only one package statement in each source file, and it applies to all types in the file.
Note: If you put multiple types in a single source file, only one can be public , and it must have the same name as the source file. For example, you can define public class Circle in the file Circle.java , define public interface Draggable in the file Draggable.java , define public enum Day in the file Day.java , and so forth.
You can include non-public types in the same file as a public type (this is strongly discouraged, unless the non-public types are small and closely related to the public type), but only the public type will be accessible from outside of the package. All the top-level, non-public types will be package private.
If you put the graphics interface and classes listed in the preceding section in a package called graphics , you would need six source files, like this:
//in the Draggable.java file package graphics; public interface Draggable < . . . >//in the Graphic.java file package graphics; public abstract class Graphic < . . . >//in the Circle.java file package graphics; public class Circle extends Graphic implements Draggable < . . . >//in the Rectangle.java file package graphics; public class Rectangle extends Graphic implements Draggable < . . . >//in the Point.java file package graphics; public class Point extends Graphic implements Draggable < . . . >//in the Line.java file package graphics; public class Line extends Graphic implements Draggable
If you do not use a package statement, your type ends up in an unnamed package. Generally speaking, an unnamed package is only for small or temporary applications or when you are just beginning the development process. Otherwise, classes and interfaces belong in named packages.
Пакеты классов, package
Пакет package позволяет логически объединить классы в наборы. Основные классы java входят в пакет 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-класс) и байт-кодами (расширением class), образующие один пакет, хранятся в одном каталоге файловой системы. Подпакеты образуют подкаталоги этого каталога. Каждый пакет создает единое пространство имен namespace. Это означает, что все имена классов и интерфейсов в пакете должны быть уникальны. Имена в разных пакетах могут совпадать, но это будут разные программные модули. Организация классов в виде пакетов позволяет избежать конфликта имен между классами. В пакете дублирование имен классов не допускается. Принадлежность класса к пакету позволяет гарантировать однозначность имен.
Чтобы указать, что класс принадлежит определенному пакету, следует использовать директиву package, после которой указывается наименование (путь) пакета :
package company.common; public class HelloWorld < public static void main(String[] args)< System.out.println ("Привет, мир!"); >>
В данном примере класс HelloWorld располагается в пакете company.common. Физически это директория «$/company/common». При создании класса в среде разработки IDE (например, Eclipse) следует указать наименование пакета, тогда IDE самостоятельно при необходимости создаст каталог на жестком диске и разместит новый класс в этом каталоге.
Можно package в классе не определять. В этом случае класс будет находиться в пакете по умолчанию, который не имеет имени «$», т.е. класс будет располагаться в корневой директории исходных кодов проекта.
Наименование пакета может быть любым, но необходимо соблюдать его уникальность в проекте. Соглашение «Code Conventions» рекомендует записывать имена пакетов строчными буквами. Тогда они не будут совпадать с именами классов, которые, по соглашению, начинаются с прописной буквы.
Стандартная библиотека Java API включает сотни классов. Каждый программист в ходе работы создает десятки своих классов. Множество классов быстро увеличивается. Java позволяет отдельные классы, решающие определенную задачу (или несколько задач), объединять в библиотеки классов в виде архивов jar. Но эти библиотеки классов, кроме стандартных, не являются частью языка java.
Импорт пакетов и классов, import
Для использования класса в приложении, его следует подключить. Так расположенный в пакете java.util класс Scanner можно подключить следующим способом :
java.util.Scanner in = new java.util.Scanner(System.in);
В этом примере при определении/создании нового объекта был указыван пакет (полный путь к файлу). Однако данный подход не всегда удобен, и в качестве альтернативы можно импортировать пакеты и классы в приложение с помощью директивы import, которая указывается после директивы package :
package company.common; import java.util.Scanner; public class HelloWorld < public static void main(String[] args)< Scanner in = new Scanner(System.in); >>
Директива import указывается в самом начале кода, после чего идет имя подключаемого класса (класс Scanner в примере).
В примере был подключен только один класс. Однако пакет java.util содержит большое количество разных классов. И чтобы не подключать по отдельности каждый класс, можно сразу подключить весь пакет :
import java.util.*; // импорт всех классов из пакета java.util
Теперь можно использовать любой класс из пакета java.util.
Возможна ситуация, когда используется два класса с одинаковым наименованием, но из разных пакетов. Это относится, например, к классам Date, которые имеются в пакете java.util и в пакете java.sql, или классам List пакетов java.util и java.awt. И если необходимо одновременно использовать оба эти класса, то необходимо указывать полный путь к классам в пакете :
java.util.Date udate = new java.util.Date(); java.sql.Date sdate = new java.sql.Date();
Следует сказать, что основные классы из пакета java.lang (например, String) подключаются автоматически и не требуют «импортирования».
Статический импорт классов, import static
В java можно использовать статический импорт. Для этого вместе с директивой import используется модификатор static :
package company.common; import static java.lang.Math.*; import static java.lang.System.*; public class HelloWorld < public static void main(String[] args) < double result = sqrt(20); out.println(result); >>
В примере определяется статический импорт классов System и Math, которые имеют статические методы. Определение статического импорта позволяет использовать статические методы без названия класса. В примере статическая функция sqrt(20) (можно и Math.sqrt(20)), возвращает квадратный корень числа. То же самое относится и к классу System, в котором определен статический объект out, поэтому можно его использовать без указания класса, если выполнен статический импорт класса System.
Пример использования классов разных пакетов
Рассмотрим простенький проект PackageExample, включающий 3 java-класса. Два java-класса располагаются в одном пакете «ru.java.online», а третий — в другом «ru.java.online.classes». Структура проекта представлена на следующем скриншоте:
Листинг базового класса, BaseClass.java
Базовый класс включает 2 поля (id, name) и методы get/set. В конструкторе значения полей инициализируется.
package ru.java.online; public class BaseClass < private String protected String name = null; public BaseClass() < this.id = "default"; this.name = "Наименование не определено"; >public String getId() < return id; >public void setId(String id) < this.id = id; >public String getName() < return name; >public void setName(String name) < this.name = name; >@Override public String toString() < return this.getClass().getName() + "\n\t"; > >
Переопределенная функция toString() возвращает наименование класса и значение полей.
Листинг наследника, Inheritor.java
Класс Inheritor.java наследует свойства базового класса BaseClass.java. Поскольку классы располаются в разных пакетах, то базовый класс необходимо импортировать.
package ru.java.online.classes; import ru.java.online.BaseClass; public class Inheritor extends BaseClass < public Inheritor() < this.name = "Наследник"; this.setId("Первый"); >>
Листинг основного класса, MainPackage.java
Основной класс включает статический метод main. Поскольку данный класс не «видит» наследника, то его приходится импортировать.
package ru.java.online; import ru.java.online.classes.Inheritor; public class MainPackage < public MainPackage() < BaseClass bc = new BaseClass(); Inheritor ir = new Inheritor(); System.out.println (bc.toString()); System.out.println (ir.toString()); >public static void main(String[] args) < new MainPackage(); System.exit(0); >>
Результат выполнения данной программы выводится в консоль в следующем виде :
ru.java.online.BaseClass: ru.java.online.classes.Inheritor:
Как видно по результату выполнения программы наименование класса включает пакет.
Говоря о полном наименовании класса следует отметить, что оно включает не только наименование пакета и наименование класса, но также и класс-загрузчик classloader. Подробно о классах-загрузчиках можно почитать здесь.