Разница между пакетом и каталогом в Java

В Java-проекте сохраняется ли все файлы.java в одной папке, если они находятся в одном пакете?

В чем разница в создании пакета для нашего проекта по сравнению с сохранением всех файлов проекта в одной папке?

Эта тема на самом деле не затрагивает мой вопрос.

Ответ 1

Существует связь между пакетом и каталогом, но это тот, который вы должны поддерживать. Если у вас есть класс, который находится в "mypackage1.mypackage2", это означает, что команда java ожидает найти его в структуре каталогов с именем "mypackage1\mypackage2" (при условии, что "обратная" нотация Windows), причем эта структура каталогов встроенный в каталог (назовите его "myjava"), имя которого находится в classpath к classpath (или находится непосредственно в "текущем каталоге").

Таким образом, ваш Java-класс (который внутренне говорит package mypackage1.mypackage2;) находится в, скажем, "\ Users\myName\myjava\mypackage1\mypackage2 \", и вы помещаете "\ Users\myName\myjava" в путь класса или иначе у вас есть текущий каталог, установленный в "\ Users\myName\myjava".

Если вы смешаете это, либо класс не будет найден вообще, либо вы получите сообщение об ошибке, подобное бесконечному "NoClassDefFoundError".

Что касается того, почему нужно использовать пакеты (и каталоги), причина связана с "пространством имен" и "разделением проблем" (посмотрите их вверх). Java было бы намного сложнее сохранить прямо, если бы не было пакетов, а все "java.lang", "java.io", "sun.misc" и другие классы были вместе. Во-первых, нужно было бы использовать "префиксы", чтобы держать их прямыми и избегать конфликтов имен. И большая часть логической группировки будет потеряна.

С вашими собственными проектами вам не нужно использовать пакеты для простых небольших программ, которые вы пишете для себя, но если вы пишете что-то, что вы могли бы дать кому-то другому, вежливо использовать такой пакет, как "myname.myproject" (заменяя свое имя и проект, конечно), поэтому человек, которого вы ему даете, может объединить его с другими без конфликтов имен.

В больших приложениях вы обнаружите, что использование дополнительных уровней разделения помогает вам поддерживать функции прямо, поэтому вы знаете, где все. Это также препятствует вам "пересекать границу" между различными функциональными областями, поэтому вы не можете вводить несвязанную логику.

Eclipse (если вы это используете) немного путает проблему, потому что она "хочет" предоставлять имена каталогов и пакетов и иногда (но не всегда) синхронизировать их.

Ответ 2

  • Пакеты предоставляют логическое пространство имен для ваших классов.

  • И эти пакеты хранятся в виде уровней каталогов (они преобразуются во вложенные каталоги), чтобы обеспечить физическую группировку (пространство имен) для ваших классов.

Также обратите внимание, что physical пространство имен должно соответствовать logical пространству имен. Вы не можете иметь свой класс с package com.demo в структуре каталогов: - \com\demo\temp\, он должен быть под \com\demo\, и этот каталог добавляется в путь к классам, чтобы ваши классы были видны JVM, когда он запускает ваш код.

Предположим, что у вас есть следующая структура каталогов:


|
+ - Sample.java (содержит класс Demo в пакете B)
|
+ - Outer.java (содержит Демо- класс - нет пакета)
|
+--B
| |
| + - Demo.class
|
+--C
| |
| + - Abc.class
|
+ - Demo.class

Предположим, ваш класс Abc.class и Demo.class (под каталогом A) не определяется ни под каким пакетом, тогда как ваш класс Demo.class (по каталогу B) определен в package B Итак, у вас должно быть два каталога в вашем пути к классам: - \A (для двух классов: - Demo.class и B.Demo.class) и \A\C (для класса Abc.class).

  • Классы под разными пакетами могут использовать одно и то же имя. Вот почему между двумя Demo.class определенными выше, конфликта не будет. Потому что они находятся в разных packages. В этом весь смысл делить их на namespaces. Это полезно, потому что у вас не будет уникальных имен для ваших классов.

Ответ 3

Понимание подсистемы загрузчика классов ответит на ваш запрос.

Со ссылкой на Inside JVM Билл Веннерс

Учитывая полное имя типа, первоклассный загрузчик классов должен каким-то образом попытаться найти файл с простым именем типа плюс ".class". Следовательно, JVM ищет определенный пользователем путь к каталогу, хранящийся в переменной среды CLASSPATH. Первоначальный загрузчик просматривается в каждом каталоге, в том порядке, в котором каталоги отображаются в CLASSPATH, пока не найдет файл с соответствующим именем: простое имя типа плюс ".class". Если тип не является частью неназванного пакета, изначальный загрузчик ожидает, что файл будет находиться в подкаталоге одного из каталогов в CLASSPATH. Имя пути для подкаталога создается из имени пакета типа. Например, если первоклассный загрузчик классов ищет класс java.lang.Object, он будет искать Object.class в подкаталоге java\lang для каждого каталога CLASSPATH.