Da wir wissen, dass die Anweisung package durch den Befehl javac ausgelöst wird, werden die zugehörigen Verzeichnisse entsprechend dem Paketnamen erstellt.

Zum Beispiel:

// MyClassB.java
package abc.xyz;

class MyClassA{
  // ...
}

class MyClassB{
  // ...
}

Nun, wenn ich diese Datei kompiliere:

javac -d . MyClassB.java

Nach der Kompilierung haben wir die folgende Verzeichnisstruktur mit den .class - Dateien.

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

Die Frage ist nun, ob diese MyClassA.class und MyClassB.class nur den kompilierten Bytecode der Klassen MyClassA und MyClassB enthalten.

Was ist mit der folgenden Aussage?

package abc.xyz;

Wird diese Anweisung während der Kompilierung entfernt? Oder diese Anweisung wird nur aus der Klasse MyClassA entfernt und verbleibt in der Klasse MyClassB, da der Name der Datei MyClassB.java war. Oder enthält die Datei MyClassB.class nach dem Kompilieren nur den Bytecode der Klasse MyClassB und das package abc.xyz; wird auch während des Kompilierens entfernt? Wenn package abc.xyz; zur Kompilierungszeit nicht entfernt wird, ist es das Problem, wenn wir diese Datei zur Laufzeit verwenden, da die Laufzeit-Engine auch die Bytecode-Version der package abc.xyz; -Anweisung auslöst Problem. Oder wird es während der Kompilierung entfernt? Oder der Bytecode wird nur für die Klassen erstellt, nicht jedoch für die Datei, die die Anweisung package abc.xyz; enthält, was dazu führt, dass package abc.xyz; nicht Teil der .class -Dateien wird.

Das Bild unten erklärt deutlich die Frage: Bildbeschreibung hier eingeben

Kann jemand erklären, was das Szenario dahinter ist? Es ist meine bescheidene Bitte an die Mitwirkenden, meine Frage nicht negativ zu bewerten, da ich einige Verwirrungen in Bezug auf Java habe. Daher möchte ich mein Konzept klären. Wenn meine Frage immer noch negativ bewertet werden kann, ist es in Ordnung, aber zumindest zu beantworten auch.

Vielen Dank !!!

0
Stack Overflow 18 Jän. 2019 im 14:18

3 Antworten

Beste Antwort

Direktiven wie die package - Deklaration sowie import - Anweisungen generieren überhaupt keinen Code. Sie wirken sich nur darauf aus, wie der Compiler Namen innerhalb derselben Kompilierungseinheit behandelt.

Also eine Erklärung wie

package abc.xyz;

public class MyClassA {

}

Erstellt eine Klasse mit dem qualifizierten Namen abc.xyz.MyClassA oder eine Klasse mit dem einfachen Namen MyClassA innerhalb des Pakets abc.xyz; beides bedeutet dasselbe.

Der qualifizierte Name wird in der Datei .class gespeichert. Dies ist die einzige relevante Information für die JVM.

Es gibt die Konvention , um solche Dateien wie SimpleName.class in einem Verzeichnis zu speichern, das vom Paketnamen abgeleitet ist, dh abc/xyz/MyClassA.class, das von javac eingehalten und von der Standardklasse verwendet wird Loader, um die Datei nachzuschlagen, wenn eine Klasse mit diesem Namen angefordert wird. Offensichtlich macht eine solche Konvention das Leben leichter.

Grundsätzlich sind andere Speichermethoden möglich und einige bekannt. Ab Java 9 hat die Referenzimplementierung ein Modul-Image-Format, davor gab es das "Shared Class Data Archive", außerdem gab es "Pack200", ein Archivformat, das zum Entfernen mit JDK 11 veraltet ist.

Beachten Sie, dass selbst JAR-Dateien, bei denen es sich um erweiterte Zip-Dateien handelt, nicht genau das sind, was Sie sehen. Eine Zip-Datei besteht aus einer linearen Folge von Dateieinträgen mit einem qualifizierten Namen. In Ihrem Fall haben Sie also zwei Einträge, deren Namen als abc/xyz/MyClassA.class und abc/xyz/MyClassB.class angegeben werden, während jede von Tools angezeigte Verzeichnisstruktur verwendet wird tatsächlich von diesen Namen abgeleitet und impliziert nicht, dass verschachtelte Einträge für abc und xyz tatsächlich existieren. Der Standardklassenlader verwendet diese Einträge jedoch genauso, als ob diese Verzeichnisstruktur vorhanden wäre. Daher besteht kein Problem mit der Einstellung, die Verzeichnisstruktur in der zip / jar-Datei gespeichert zu haben.

Ab Java 9 können jedoch verschiedene Versionen für dieselbe Klasse verfügbar sein, die je nach aktueller Java-Version ausgewählt werden müssen. Das dafür verwendete Namensschema ist nicht Teil der Konvention, die javac beim Speichern der Dateien verwendet.

3
Holger 24 Jän. 2019 im 10:04

Es geht nirgendwo hin, es wird als class abc.xyz.MyClassA kompiliert. Sie können dies sehen, wenn Sie dieses .class beispielsweise mit javap dekompilieren würden.

2
Eugene 18 Jän. 2019 im 11:23

Wenn Sie die .class-Datei einer Ihrer Klassen öffnen, können Sie die darin enthaltenen Paketdetails sehen. Wenn Sie in Ihrem Fall MyClassA.class im Texteditor öffnen, sehen Sie so etwas wie abc/xyz/MyClassA. Die JVM verwendet es wie abc.xyz.MyClassA. Das ist der Grund, warum wir diese Klasse wie import abc.xyz.MyClassA verwenden müssen, wenn wir sie in einer anderen Klasse verwenden müssen.

1
DK Ansh 18 Jän. 2019 im 11:30