Java. Удаляется ли оператор пакета в файле .class?

Поскольку мы знаем, что оператор package при запуске командой javac создает связанные каталоги в соответствии с именем пакета.

Например:

// MyClassB.java
package abc.xyz;

class MyClassA{
  // ...
}

class MyClassB{
  // ...
}

Теперь, когда я компилирую этот файл:

javac -d . MyClassB.java

После компиляции у нас будет следующая структура каталогов с файлами .class.

/
 |___ abc
    |___ xyz
        |___ MyClassA.class
        |___ MyClassB.class

Теперь вопрос: эти MyClassA.class и MyClassB.class содержат только скомпилированный байткод классов MyClassA и MyClassB?

А как насчет следующего утверждения?

package abc.xyz;

Этот оператор удаляется во время компиляции? Или это утверждение удаляется только из класса MyClassA и остается в классе MyClassB, потому что имя файла было MyClassB.java. А может, файл MyClassB.class после компиляции содержит только байт-код класса MyClassB, а package abc.xyz; тоже удаляется при компиляции? Если package abc.xyz; не будет удален во время компиляции, это будет проблемой, когда мы будем использовать этот файл во время выполнения, потому что механизм выполнения также вызовет версию байт-кода инструкции package abc.xyz;, поэтому, это было бы проблемой. Или он удаляется при компиляции? Или байт-код создается только для классов, а не для файла, содержащего инструкцию package abc.xyz;, в результате чего package abc.xyz; не становится частью файлов .class .

Картинка ниже ясно объясняет вопрос:Java. Удаляется ли оператор пакета в файле .class?

Кто-нибудь может объяснить, что за сценарий стоит за этим? Это моя скромная просьба к участникам не ставить отрицательную оценку моему вопросу, потому что у меня есть некоторые недоразумения относительно java, поэтому я хочу прояснить свою концепцию. Если мой вопрос все еще может быть отмечен отрицательной оценкой, тогда все в порядке, но, по крайней мере, ответьте также.

Спасибо !!!

Пожалуйста, не могли бы вы пояснить эту фразу? " Если пакет abc.xyz; не удален во время компиляции, тогда это будет проблемой, когда мы будем использовать этот файл во время выполнения, потому что механизм выполнения также вызовет версию байт-кода инструкции пакета abc.xyz;, поэтому будет проблема." Что вы подразумеваете под «версией байт-кода оператора пакета abc.xyz триггера»?

Jon Skeet 18.01.2019 12:23

Я имею в виду, что целью оператора package abc.xyz; является создание каталогов и размещение файлов .class внутри каталога xyz, поэтому время выполнения будет выполнять ту же работу, что и время компиляции? Так не в этом ли проблема? Поскольку среда выполнения скажет, давайте создадим каталоги из-за оператора package abc.xyz;, так что, как я понимаю, теперь я не знаю, что за сцена стоит.

Stack Overflow 18.01.2019 12:27

Пусть говорит, что у меня есть выписка System.out.print("Hello world");. Теперь, когда эта программа запустится, Hello World будет распечатан, верно? Допустим, у меня есть оператор package abc.xyz;. Теперь, когда эта программа запустится, она снова создаст каталоги и файлы .class? я надеюсь, что вы получили меня сейчас !!! Я говорю о времени выполнения.

Stack Overflow 18.01.2019 12:31

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

Jon Skeet 18.01.2019 12:32

«Я имею в виду, что цель оператора package abc.xyz; состоит в том, чтобы создать каталоги и поместить файлы .class в каталог xyz» - нет, это указать пакет для классов, объявленных в этом исходном файле. Это не «код, который работает». Именно компилятор решает, что ему делать с файлами классов. Другой компилятор может вообще не использовать файловую систему, но ему все равно нужно знать пакет класса.

Jon Skeet 18.01.2019 12:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
719
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Он нигде не идти, он скомпилирован как class abc.xyz.MyClassA. Вы можете видеть это, если бы вы декомпилировали этот .class, например, используя javap.

Но результатом оператора package abc.xyz; является создание каталогов и размещение файла .class в каталоге. Итак, не будет ли среда выполнения создавать каталог снова и снова при запуске этой программы, разве это не проблема? или оператор package abc.xyz; не выполняется во время выполнения?

Stack Overflow 18.01.2019 12:29

Пусть говорит, что у меня есть выписка System.out.print("Hello world");. Теперь, когда эта программа запустится, Hello World будет распечатан, верно? Допустим, у меня есть оператор package abc.xyz;. Теперь, когда эта программа запустится, она снова создаст каталоги и файлы .class? я надеюсь, что вы получили меня сейчас !!! Я говорю о времени выполнения.

Stack Overflow 18.01.2019 12:31

@SunnyKhan «запускает» уже скомпилированные классы, они не компилируются снова. вы понимаете это правильно?

Eugene 18.01.2019 12:52

Итак, package abc.xyz; не является частью среды выполнения?

Stack Overflow 18.01.2019 12:57
Часть 1 "Но результат пакета abc.xyz; оператор для создания каталогов" нет, оператор package abc.xyz: только проверяет, находитесь ли вы в правильном каталоге, если вы не компилятор или текстовый редактор ide скажет что-то вроде имя пакета не совпадает с именем каталога снова package abc.xyz:НИЧЕГО не создает, это похоже на приведение --> допустим, класс собака расширяет класс животного, которого вы можно написать что-то вроде Animal a = new Dog(); и тогда вы могли бы написать Dog d = (Dog) a; если бы a было каким-то другим животным, например a=new Cat(); вы получите ошибку времени компиляции
Harry 19.11.2019 08:34

Приведение Часть 2 не изменяет объект, он не превращает его в собаку, он аналогичен пакету, он только там, чтобы проверить, находится ли ваш файл в правильном каталоге.

Harry 19.11.2019 08:36

Если вы откроете файл .class любого вашего класса, вы увидите внутри него детали пакета. В вашем случае, если вы откроете MyClassA.class в текстовом редакторе, то увидите что-то вроде abc/xyz/MyClassA. JVM будет использовать его как abc.xyz.MyClassA. Вот почему, если нам нужно использовать этот класс в каком-то другом классе, нам нужно использовать его, как import abc.xyz.MyClassA.

Пусть говорит, что у меня есть выписка System.out.print("Hello world");. Теперь, когда эта программа запустится, Hello World будет распечатан, верно? Допустим, у меня есть оператор package abc.xyz;. Теперь, когда эта программа запустится, она снова создаст каталоги и файлы .class? я надеюсь, что вы получили меня сейчас !!! Я говорю о времени выполнения.

Stack Overflow 18.01.2019 12:31

Пакет используется для группировки типов Java (классы, интерфейсы, перечисления и т. д.). Поэтому, когда вы используете пакет в своей Java-программе, он связывает эти типы Java в одном пакете.

Deepak Kumar 18.01.2019 12:35

Пожалуйста, прочитайте это от оракула для получения более подробной информации. Пакеты

Deepak Kumar 18.01.2019 12:36
Ответ принят как подходящий

Такие директивы, как объявление package, а также операторы import, вообще не генерируют никакого кода, они только влияют на то, как компилятор будет обрабатывать имена в пределах одной единицы компиляции.

Итак, объявление типа

package abc.xyz;

public class MyClassA {

}

создает класс с полным именем abc.xyz.MyClassA или класс с простым именем MyClassA в пакете abc.xyz; оба означают одно и то же.

Полное имя хранится в файле .class, который является единственной важной информацией для JVM.

Существует соглашение для хранения такого файла, как SimpleName.class, в каталоге, полученном из имени пакета, то есть abc/xyz/MyClassA.class, привязанного javac и используемого стандартными загрузчиками классов для поиска файла, когда запрашивается класс с таким именем. Очевидно, что наличие такого соглашения облегчает жизнь.

В принципе возможны и другие способы хранения, и некоторые из них известны. Начиная с Java 9 эталонная реализация имеет формат образа модуля, до этого был «архив данных общего класса», далее был «Pack200», формат архива, который устарел для удаления с JDK 11.

Обратите внимание, что даже jar-файлы, которые представляют собой расширенные zip-файлы, — это не совсем то, что вы видите. ZIP-файл состоит из линейной последовательности файловых записей, имеющих полное имя, поэтому в вашем случае у вас будет две записи, сообщающие свои имена как abc/xyz/MyClassA.class и abc/xyz/MyClassB.class, тогда как любая структура каталогов, отображаемая инструментами, фактически получена из этих имен и не подразумевает, что вложенные записи для abc и xyz действительно существуют. Тем не менее, стандартный загрузчик классов также будет использовать эти записи так же, как если бы эта структура каталогов существовала, поэтому нет проблем с сохранением структуры каталогов в файле zip/jar.

Но, начиная с Java 9, для одного и того же класса могут быть разные версии, которые следует выбирать в зависимости от текущей версии Java. Схема именования, используемая для этого, не является частью соглашения, используемого javac при хранении файлов.

В самом деле? структура файлов jar может не существовать, и такая структура папок получена из фактического имени?

Eugene 24.01.2019 15:30

@Eugene имя записи zip-файла, не обязательно фактическое имя класса. Это означает, что вы можете создать zip-файл, например. через ZipOutputStream, создайте одну запись через putNextEntry с именем foo/bar/baz, и когда вы откроете ее с помощью файловой системы zip или аналогичного инструмента, ориентированного на файловую систему, он покажет вам каталог foo, содержащий каталог bar, содержащий файл baz, тогда как zip-файл имеет только одну запись. Обычно zip-файлы вообще не содержат записей для каталогов.

Holger 24.01.2019 15:53

Другие вопросы по теме