Java-kompilierte Klassen enthalten Dollarzeichen

80

Ich habe Eclipse als meine Entwicklungs-IDE verwendet. Ich verwende es auch, um meine Anwendung in eine JAR-Datei zu exportieren. Wenn ich mir meine Klassen in der JAR-Datei ansehe, enthalten einige meiner Klassen den Namen dieser Klasse, ein Dollarzeichen und dann eine Zahl. Beispiel:

  • Finden Sie $ 1.class
  • Finden Sie $ 2.class
  • Finden Sie $ 3.class
  • Find.class

Ich habe bemerkt, dass dies bei größeren Klassen der Fall ist. Liegt das daran, dass die Klassen so groß werden, dass sie in mehrere Klassen kompiliert werden? Ich habe in mehreren Foren gegoogelt und gesucht und die Java-Dokumentation durchsucht, aber nichts gefunden, was damit zu tun hätte. Könnte jemand erklären?

Frizinator
quelle
Beispielcode zum Testen dieses Problems github.com/Aksi0m/SampleFor123686419
Prags
Laut Antwort des Google-Teams issuetracker.google.com/issues/123736741 ist dies intern behoben und wird in der nächsten Version von Navigation verfügbar sein.
Prags

Antworten:

109

Innere Klassen, falls in Ihrer Klasse vorhanden, werden kompiliert und die Klassendatei wird ClassName$InnerClassName. Bei anonymen inneren Klassen werden diese als Zahlen angezeigt. Die Größe der Klasse (Java-Code) führt nicht zur Generierung mehrerer Klassen.

ZB diesen Code gegeben:

public class TestInnerOuterClass {
    class TestInnerChild{

    }

    Serializable annoymousTest = new Serializable() {
    };
}

Klassen, die generiert werden, sind:

  1. TestInnerOuterClass.class
  2. TestInnerOuterClass$TestInnerChild.class
  3. TestInnerOuterCasss$1.class

Aktualisieren:

Die Verwendung einer anonymen Klasse wird nicht als schlechte Praxis angesehen, sondern hängt nur von der Verwendung ab.

Überprüfen Sie diese Diskussion auf SO

mprabhat
quelle
1
Okay, ist es schlecht, eine anonyme Klasse zu haben? Ich verstehe nicht ganz, wie es funktioniert. Wenn ich eine neue Instanzvariable einer Klasse in einer Klasse erstelle, ist das eine anonyme Klasse?
Frizinator
Nein, es ist nicht schlecht, eine anonyme Klasse zu haben, es hängt von der Verwendung ab. Aktualisiert meinen Beitrag
mprabhat
4
Aufzählungen, die einen Klassenkörper enthalten, generieren automatisch eine anonyme innere Klasse, die die Aufzählungsklasse erweitert, und generieren somit eine weitere Klassendatei mit einem $ darin.
Dlaidlaw
1
Auch wenn die innere Klasse privat ist, wird eine zusätzliche Klasse mit dem Namen OuterClass $ 1.class
SandeepGodara
@mprabhat: Gibt es in Android Studio einen Mechanismus, um die Hierarchie oder Liste dieser Klassen anzuzeigen?
user1090751
15

Dies liegt daran, dass Sie in dieser größeren Klasse anonyme Klassen haben. Sie werden mit dieser Namenskonvention kompiliert.

Siehe Das Rätsel der anonymen Klasse

jjathman
quelle
9

Zusätzlich zu den oben von @mprabhat vorgestellten Fällen können die anderen Fälle sein:

  1. Wenn Ihre Klasse eine Enum- Variable enthält, wird auch dafür eine separate Klasse generiert. Der Name der generierten .class lautet ClassName $ Name_of_enum .
  2. Wenn Ihre Klasse X erbt, dh eine andere Klasse Y erweitert , wird eine .class mit dem Namen ClassName $ 1.class oder ClassName $ 1 $ 1.class generiert
  3. Wenn Ihre Klasse X eine Schnittstelle Y implementiert , wird eine .class mit dem Namen ClassName $ 1.class oder ClassName $ 1 $ 1.class generiert .

Diese Fälle sind Ableitungen meiner Inspektion von .class-Dateien in jar.

SGuru
quelle
Ich habe eine Klasse, die keines dieser Kriterien erfüllt, und class.getName () ist immer noch falsch - für Group.java wird Group _ $$ _ jvst248_20 zurückgegeben. Ich habe keine Ahnung, was los ist. Definitiv keine Aufzählungen, Erweiterungen oder Implementierungen.
Amalgovinus
0

Um Ihren Kommentar zu beantworten, sind anonyme Klassen schlecht. Sie sind definitiv nicht. Berücksichtigen Sie dies, um einem JButton einen Aktionslistener zuzuweisen:

JButton button = new JButton(...);
button.addActionListener(new ActionListener() { ... });

oder dies, um eine Sortierung ohne Berücksichtigung der Groß- und Kleinschreibung nach der Eigenschaft "name" durchzuführen

Collections.sort( array, new Comparator<Foo>() {
    public int compare(Foo f1, Foo f2) {
        return f1.getName().toLowerCase().compareTo(f2.getName().toLowerCase());
    }
});

Sie werden auch viele Runnable und Callable als anonyme Klassen sehen.

Matt
quelle