Если мы позвоним в метод GetPackage в объекте класса, мы можем получить объект пакета, описывающий пакет, в котором находится класс (класс пакетов определяется в java.lang). Мы также можем использовать имя пакета для получения объекта пакета, вызывая статический метод GetPackage или вызывая статический метод GetPackages (который возвращает массив, состоящий из всех известных пакетов в системе). Метод GetName может вернуть полное имя пакета.
Использование объектов пакета полностью отличается от других типов отражений, то есть мы не можем создавать или манипулировать пакетами во время выполнения. Мы можем использовать объекты пакета для получения информации о пакетах, таких как цель пакета, который создал пакет, версию пакета и т. Д. Мы откладым это содержимое, пока не обсудим их подробно.
Именование пакета
Названия пакетов должны избегать конфликтов с другими пакетами, поэтому выбор имени, которое является значимым и уникальным, является важным аспектом дизайна пакетов. Тем не менее, программисты по всему миру разрабатывают пакеты, и нет никакого способа узнать, кто использовал какое название пакета, поэтому выбор единственного названия пакета - проблема. Если мы определим, что пакет используется только в нашей организации, у нас может быть внутренний арбитр, чтобы убедиться, что между проектами нет конфликта имен.
Но для всего мира этот подход не практичен. Все идентификаторы пакетов - это простые имена, и лучший способ убедиться, что имя пакета будет использовать имя доменного домена. Если компания, в которой мы работаем, это Magic.lnc, а доменное имя компании - Magic C.com, то объявление пакета атрибутов должно быть:
пакет com.magic.attr;
Обратите внимание, что составные элементы доменного имени здесь расположены в обратном порядке обычного доменного имени.
Если мы примем эту идиому, имена пакетов, которые мы используем, не будут противоречить кому -либо другому, за исключением возможного конфликта в нашей организации. Если в нашей организации действительно существует конфликт (вероятно, крупное предприятие), то мы можем использовать более конкретные доменные имена для дальнейшей квалификации. Многие крупные компании имеют внутренние субдомены, такие как Восток и Европа, которые могут быть использованы для дальнейшего квалификации названия пакета:
Package Corn.magic.japan.attr;
Использование этого решения может сделать имя пакета очень длинным, но оно относительно безопасно. Программисты, использующие эту технику, не выберут одно и то же имя пакета, и программисты, которые не используют эту технику, не выберут имя, которое мы используем.
Содержимое пакета
Содержимое пакета должно быть тщательно разработано, чтобы они включали только функционально релевантные классы и интерфейсы. Занятия в пакете могут свободно получить доступ к не-частным членам других классов в пакете, и некоторые классы могут даже иметь достаточные разрешения для доступа к внутренним деталям других классов. Чтобы избежать неправильных классов, мы должны защищать членов класса. Любого участника, не объявленного частным, может получить доступ к всем другим типам в одном и том же пакете, поэтому любые не связанные с ним классы могут быть более вероятной скоординированной, чем мы ожидаем.
Пакеты также предоставляют логическую группировку для программистов, ищущих полезные интерфейсы и классы. Пакеты, состоящие из не относящихся к делу классов, мешают программистам, какие интерфейсы и классы полезны, а логическая группировка классов может помочь программистам повторно использовать код, потому что программисты могут найти то, что им нужно легче, путем логической группировки. Если пакет содержит только связанные, тесно связанные наборы типов, это означает, что мы можем дать типу несколько более интуитивно понятных имен, чтобы избежать конфликтов имен.
Пакеты могут быть вложены. Например, Java.Lang - это вложенный пакет, в котором пакет Lang вложен в большую упаковку Java, а в пакете J Ava также содержится некоторые другие пакеты. Гнездование заставляет связанные пакеты образуют систему именования с иерархической структурой.
Например, чтобы создать набор пакетов для адаптивных систем, таких как нейронные сети и генетические алгоритмы, мы можем назвать пакеты с разделенными точками именами для создания вложенных пакетов:
пакет адаптивен. нейронная сеть;
Исходной файл, содержащий приведенный выше заявление об объявлении, находится в пакете Adaptive.neralnet, а сам пакет Adaptive.neralnet - это подпака адаптивного пакета. Адаптивный пакет может содержать некоторые классы, связанные с общими адаптивными алгоритмами, такими как классы операторов задачи обобщения или эталонные классы. Пакеты, которые находятся в более глубоком положении в иерархии (например, Adaptive.Neu-ralnet или Adaptive.genetic), содержат классы, связанные с определенным типом адаптивного алгоритма.
Гнездование пакетов - это всего лишь инструмент для организации связанных пакетов, и оно не обеспечивает никаких специальных прав доступа между пакетами.
Код класса в пакете Adaptive.Genetic не может получить доступ к участникам в пакете Adaptive или Adaptive.neralnet, который имеет права доступа к пакетам, а область пакета применима только к конкретным пакетам. Гнездование пакетов может группировать соответствующие пакеты и помочь программистам найти желаемый класс на логическом уровне более удобно, но помимо этого он не приносит никаких других преимуществ.
Примечания к пакетам
Пакет также может иметь аннотации. Но проблема заключается в том, что, поскольку пакеты являются организационной структурой без сущностей исходного кода, и они не имеют фактического определения, их нельзя аннотировать, как классы или методы, поэтому аннотация пакета может быть достигнута только путем аннотирования заявления об объявлении пакета в исходном файле. Тем не менее, в каждом пакете может быть только одно объявление пакета, в которых могут быть аннотации, которые действуют на него.
Итак, как вы аннотируете пакеты? Фактически, Java не заставляет программистов использовать какой -то способ справиться с правилом «Одиночный аннотированный оператор пакета». Рекомендуемый способ состоит в том, чтобы создать файл с именем пакета-i nfo.java в каталоге пакетов, в котором хранятся только операторы пакета и аннотации пакета, не размещая ничего другого. Например, файл пакета Info.java для пакета ATTR выглядит так:
@Packagespec (Назовите два «ATTR Project», version = "1.0" @Developmentsite ("attr.project.org") @DevelopmentModel ("Open-Source") ATRT;Packagespec, разработки и разработка OpmentModel используются для изменения типов аннотаций. Конечно, у них есть стратегии сохранения времени выполнения. Файл Package-info.java должен быть скомпилирован с другими исходными файлами в пакете.
Мы рекомендуем разместить всю информацию, связанную с пакетом, в файл пакета info.java. Если вы сделаете это, вы можете разместить комментарии документов в начале файла, чтобы эти документы были аннотированы в качестве пакетных документов.
Доступ к пакетам
При объявлении доступности классов верхнего уровня и интерфейсов верхнего уровня в пакетах есть два варианта: доступ к пакетам (пакет) и публичный доступ (общедоступный). К классам или интерфейсам, измененным с помощью общественности, можно получить доступ к коду вне пакета, в то время как типы, не украшенные общественностью, имеют область пакета: к ним можно получить доступ к другим кодам в том же пакете; Но они скрыты для кодов вне пакета, даже в кодах подпакетов. При объявлении типов мы должны объявлять только те типы, которые другие программисты должны использовать в качестве общественности, и скрывать те типы, которые принадлежат к деталям реализации пакета. Эта технология предоставляет нам большую гибкость, и, поскольку программисты не полагаются на эти типы деталей реализации, к которым они не могут получить доступ, мы можем свободно изменить их, когда хотим изменить детали реализации.
Участники класса, которые не объявляются как общедоступные, защищенные или частные, могут быть доступны непосредственно любым кодом внутри пакета, но скрыты из -за пределов пакета. Другими словами, модификатор доступа по умолчанию - «пакет», за исключением членов интерфейса, а его модификатор доступа по умолчанию является «публичным».
Поля или методы, которые не объявляются частными в пакете, могут быть доступны всем другим кодом в этом пакете, поэтому классы в одном пакете считаются «дружественными» или «доверенными». Это позволяет нам определить структуру приложения, которая объединяет предопределенный код и код заполнителей, где код заполнителя переопределен подклассом класса Framework. Предопределенные коды могут использовать модификаторы доступа к пакетам, чтобы другие совместные коды в пакете могли напрямую доступ к ним, но для пользователей вне пакета эти коды недоступны. Тем не менее, подпакинги пакетов, где расположены эти коды, не доверяют и наоборот. Например, код, измененный с помощью модификатора доступа к пакетам в пакете DIT, не может быть доступен по коду в своем детском пакете dit.dat, и наоборот.
Следовательно, каждый тип определяет три разных контракта:
.publi. Контракт: определяет основную функцию типа.
.Protected Contract: определяет функции, доступные для подклассов для целей специализации.
.package Contract: определяет функции, которые могут быть получены другим кодом в пакете для достижения сотрудничества между типами в пакете. Все эти контракты требуют тщательного рассмотрения и дизайна.
Метод доступности и покрытия
Только методы, которые доступны в суперклассах, могут быть перезаписаны на подклассах. Если метод в суперклассе не может быть доступен, метод не может быть переопределен в подклассе, даже если метод в подклассе имеет то же имя, что и метод. Когда метод вызывается во время выполнения, система рассматривает его доступность и, таким образом, определяет, какая его реализация работает.
Следующий специально построенный пример объясняется более четко. Предположим, мы объявляем класс абстрактной базы в пакете P1:
Пакет P1; {Ab ab abab public abstract class base private void pri () {print ("stractbase.pri ()"):} void pac () {print ("stractbase.pac ()"); } protected void pro () {print ("stractbase.pro ()"); } public void pub () {print ("stractbase.pub ()");} public final void show () pri (); pac (); Pro (); паб(); }}В этом классе мы определяем 4 метода, каждый из которых с различным модификатором доступа, и тело метода только идентифицирует себя. Метод показывает, что эти 4 метода по текущему объекту по очереди. При применении этого метода к различным объектам подкласса он может объяснить, какая реализация этих методов называется.
Теперь мы определяем Class Concetel, который расширяет класс AbstractBase, но находится в пакете P2:
Пакет P2; Импорт p1.abstractbase public class concretel extrables rastractbase {public void pri () {print ("concetel.pri ()");} public void pac () {print ("concetel.pac ()");} public void pro () {print ("concretel.pro ()");} public void pub () {printel.) }4 метода в Superclass переработаны в этом классе, и их реализации изменены, которые сообщают, что они принадлежат к классу Con-Cretel. В то же время их права доступа были изменены на публику для другого кода для доступа. Выполнить следующий код
New Concetel (). Show ():
Будет сгенерирован следующий выход:
AbstractBase.pri () AbstractBase.pac () concetel.pro () concetel.pub ()
Поскольку частный метод PRI не может быть доступен с помощью подклассов (или других классов), метод шоу всегда вызывает реализацию метода PRI в классе AbstractBase. Метод PAC с разрешениями доступа к пакетам в классе AbstractBase не может быть доступен с помощью Concetel, поэтому реализация метода PAC в классе Concetel не может переопределить определение в классе AbstractBase, поэтому метод Show называет метод AbstractBase.pac. Метод PRO и метод паба доступны в классе Concetel и также могут быть перезаписаны, поэтому метод шоу вызывает реализацию этих двух методов в классе Concetel.
Следуйте нашему ноге, знаменитому классу Class Boncrete2, чтобы расширить Class Concetel, а затем мы помещаем ее в тот же пакет P1, что и класс AbstractBase ':
Пакет P1; Импорт p2.concretel public class concrete2 Extends concetel {public void pri () {print ("concret2.pri ()");} public void pac () {print ("concrete2.pac ()");} public void pro () {print ("concrete2Поскольку методы в бетоне имеют права общественного доступа, к ним можно получить доступ в бетоне2, и каждый метод в бетоне 2 покрывает соответствующие методы отдельно. Кроме того, поскольку Concrete2 и Abstractbase находятся в том же пакете, метод AbstractBase.PAC также можно получить в Concrete2, а метод Concrete2.pac может быть переопределен. Вызовите метод шоу на объекте Concrete2, и результат печати заключается в следующем:
AbstractBase.pri () Concrete2.pac () Concrete2.pro () Concrete2.pub ()
Наконец, мы определяем Class Concrete3, чтобы расширить Class Concrete2 и поместим его в пакет P3:
Пакет P3 Import P1.concrete2; Public Class Concrete3 Extends Concrete2 {public void pri () {print ("concrete3.pri ()");} public void pac q {print ("concrete3.pac ()");} public void pro () {print ("concrete3.pro ()");} public void pub () {print3.pub () "Вызовите метод шоу на объекте Concrete3, и результат печати заключается в следующем:
AbstractBase.pri () Concrete3.pac () Concrete3.pro () Concrete3.pub ()
Здесь метод Concrete3.PAC выглядит так, как будто он переопределяет недоступный метод AbstractBase.PAC, но на самом деле метод Concrete3.PAC переопределяет метод Concrete2.pac, и метод Concrete2.pac переопределяет метод AbstractBase.PAC, поэтому метод Concrete3.PAC косвенно переопределяет метод AbstractBase.PAC. Изменив метод PAC в Class Concrete2 как наличие разрешений на публичный доступ, к нему можно получить доступ и перезаписан любым подклассом.
Объекты и спецификации упаковки
Пакеты обычно реализуют некоторые спецификации и обычно из организации. Объекты пакета отличаются от других типов отражений и не могут использоваться для создания или эксплуатации пакетов, но могут служить только базой знаний для предоставления информации, которая предоставляет информацию о спецификациях, реализованных пакетом (заголовок, поставщик и номер версии) и информацию о реализации самого пакета (заголовок, поставщик и номер версии пакета). Хотя пакеты обычно поступают от отдельных организаций, спецификации, которые она реализует (такие как библиотеки статистического анализа), могут быть определены другими организациями. Программы с использованием пакетов, возможно, должны знать версию спецификации, реализованной пакетом, так что можно использовать функции, определенные только в определенной версии. Точно так же эти программы также могут знать, какая версия реализации предоставлена для нее, главным образом для работы с возможными недостатками в разных версиях. Некоторые из основных методов класса пакетов разрешают доступ к этой информации:
・ Public Stri ng getName (): возвращает имя пакета.
.public String GetSpecificationTitle P: возвращает заголовок спецификации, реализованной пакетом. Если заголовок неизвестен, верните NULL,
.public String getSpecificationVersion (): возвращает строку, описывающую информацию версии спецификации, реализованной пакетом. Если информация о версии неизвестна, верните NULL,
.public String GetSpeciationVendor Q: возвращает имя поставщика, который владеет и поддерживает спецификации, реализованные пакетом. Если поставщик неизвестен, верните ноль,
.public String getimplerentationTitle (): возвращает заголовок реализации, предоставленной пакетом. Если заголовок неизвестно, он возвращает NULL, ・ public String getImplementationVersion (): возвращает строку, описывающую информацию версии реализации, предоставленной пакетом. Если информация о версии неизвестна, она возвращает NULL,
・ Public String getImplemplementationVendor (): возвращает имя организации (поставщика), которая обеспечивает реализацию. Если организация неизвестна, вернуть ноль,
Например, если мы извлеките эту информацию из пакета java.lang в нашей системе, мы получим следующие результаты:
Название спецификации: Java Platform Platform Specization Спецификация Версия: 1.4 Спецификация поставщик: Sun Microsystems, Inc. Название реализации: Версия реализации среды выполнения Java: 1.5.0_02 поставщик реализации: Sun Microsystems, Inc.
Канонический номер версии состоит из неотрицательных чисел, разделенных периодами делимитиров, таких как «2,0» или '11 .0.12 '. Этот шаблон позволяет нам вызвать метод Iscompatible с сравнением номер версии, который следует за этим шаблоном с номером версии пакета. Если номер версии пакета больше или равен номеру версии преемника, то метод возвращает true. Это сравнение сравнивает только отдельное число, разделенное периодом за раз. Если какое -либо из этих чисел меньше, чем соответствующая позиция в номере пропущенной версии, то две версии несовместимы. Если одно из номеров версий длиннее другого, отсутствующая часть в коротких номерах версий будет считаться нулевым. Например, если канонический номер версии пакета составляет «1.4», и мы сравниваем его с «1.2», «1.3.1». Или «.1.81., Тогда верно будет возвращено; но при сравнении с «1.4.2 '.
Не существует указанного формата для номера версии реализации, поскольку различные организации, которые предоставляют реализацию, будут по -разному определять версию реализации. Единственное сравнение, которое можно провести между версиями реализации, - это проверить, является ли версия одинаковой, где нет предположения о обратной совместимости.
Пакет может быть запечатан, что означает, что классы больше не могут быть добавлены в упаковку. Открытые пакеты могут содержать классы из разных мест в пути поиска класса, в то время как содержимое герметичного пакета должно поступать из одного и того же места - либо конкретного архива, либо местоположения, указанного URL. Есть два способа определить, закрыт ли пакет:
.public boolean asseal p: return trueo, если упаковка запечатана
.public Boolean Issealed (URL URL): вернуть true, если упаковка запечатана для данного URL, то есть классы в упаковке могут быть загружены из данного URL. Если класс в пакете не может быть загружен из данного URL -адреса, или пакет не запечатан, то FALSE возвращается, а информация о спецификации и реализации пакета обычно предоставляется как часть манифестного файла, хранящегося в пакете - например, как часть манифестного файла в архиве Java (JAR), как описано в разделе 25.9.2, «Archive File Java.Ut.Ut». Когда класс в упаковке загружается, эта информация читается человеком. ClassLoader может динамически определить объект пакета для класса, который он хочет загрузить:
.Protected Package Denepackage (имя строки, строка Spectitle, String Spepersion, String Specvendor, String ImpltiTle, строка, внедрение, String Implvendor, URL Sealbase): этот метод вернет объект пакета с заданным именем пакета и спецификацией и значением реализации соответствующей цитатой. Если параметр Sealbase Null, то упаковка не запечатана, в противном случае пакет герметичен для этого URL: объект пакета класса должен быть определен до определения класса, и имя пакета должно быть уникальным в загрузчике класса. Если имя пакета повторяется с существующим именем, будет выбрана работа 11EGA1ArgumentException.
Мы можем вызвать метод GetPackage объекта класса данного класса, чтобы получить объект пакета этого класса. Мы также можем позвонить в статический пакет. Оба метода связаны с загрузчиком класса, который вызывает их код, потому что эти коды будут вызывать методы Get-Package или GetPackages их загрузчика класса. Методы загрузчиков этих классов будут искать конкретный загрузчик класса и все его родительские загрузчики класса, и если настройки не будут сделаны для текущего загрузчика класса, в настоящее время будет использоваться системный загрузчик класса. Обратите внимание, что если пакет неизвестен, метод ClassLader будет возвращать NULL, потому что в настоящее время не было загружено никакого типа в пакете.