Skompilowane klasy java zawierają znaki dolara

83

Używam Eclipse jako mojego środowiska programistycznego. Używam go również do eksportu mojej aplikacji do pliku .jar. Kiedy patrzę na moje klasy w pliku .jar, kilka z nich zawiera nazwę tej klasy, znak dolara, a następnie liczbę. Przykład:

  • Znajdź klasę $ 1.class
  • Znajdź $ 2.class
  • Znajdź $ 3.class
  • Find.class

Zauważyłem, że robi to na większych klasach. Czy to dlatego, że klasy stają się tak duże, że kompiluje je w wiele klas? Wyszukałem w Google i przeglądałem wiele forów, przeszukałem dokumentację Java, ale nie znalazłem niczego, nawet co z nią związane. Czy ktoś mógłby to wyjaśnić?

Frizinator
źródło
Przykładowy kod do testowania tego problemu github.com/Aksi0m/SampleFor123686419
Prags
Zgodnie z odpowiedzią zespołu Google issuetracker.google.com/issues/123736741 problem został rozwiązany wewnętrznie i będzie dostępny w następnej wersji Nawigacji.
Prags

Odpowiedzi:

111

Klasy wewnętrzne, jeśli istnieją w twojej klasie, zostaną skompilowane, a plik klasy będzie ClassName$InnerClassName. W przypadku klas wewnętrznych Anonymous pojawi się jako liczby. Rozmiar klasy (kod Java) nie prowadzi do generowania wielu klas.

Np. Podając ten fragment kodu:

public class TestInnerOuterClass {
    class TestInnerChild{

    }

    Serializable annoymousTest = new Serializable() {
    };
}

Klasy, które zostaną wygenerowane, to:

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

Aktualizacja:

Używanie klasy anonimowej nie jest uważane za złą praktykę, zależy tylko od sposobu użycia.

Sprawdź dyskusję na temat SO

mprabhat
źródło
1
Okej, więc czy to źle mieć anonimowe zajęcia? Nie bardzo rozumiem, jak to działa. Jeśli utworzę nową zmienną instancji klasy w klasie, to jest klasa anonimowa?
Frizinator,
Nie, nie jest źle mieć anonimową klasę, zależy to od zastosowania. Zaktualizowałem mój post
mprabhat
4
Wyliczenia zawierające treść klasy automatycznie generują anonimową klasę wewnętrzną, która rozszerza klasę wyliczenia, a tym samym generuje inny plik klasy zawierający znak $.
dlaidlaw 07.07.15
1
Również jeśli klasa wewnętrzna jest prywatna, generowana jest dodatkowa klasa o nazwie OuterClass $ 1.class
SandeepGodara
@mprabhat: czy w Android Studio istnieje mechanizm umożliwiający wyświetlenie hierarchii lub listy tych klas?
user1090751
15

Dzieje się tak, ponieważ masz anonimowe klasy w tej większej klasie. Są kompilowane przy użyciu tej konwencji nazewnictwa.

Zobacz Zagadka klasy anonimowej

jjathman
źródło
9

Oprócz powyższych przypadków przedstawionych przez @mprabhat, innymi przypadkami mogą być:

  1. jeśli klasa zawiera zmienną wyliczeniową , zostanie wygenerowana oddzielna klasa. Nazwa wygenerowanej klasy to ClassName $ Name_of_enum .
  2. Jeśli twoja klasa X dziedziczy, tj. Rozszerza inną klasę Y , wówczas zostanie wygenerowany .class o nazwie ClassName $ 1.class lub ClassName $ 1 $ 1.class
  3. Jeśli twoja klasa X implementuje interfejs Y , wtedy będzie wygenerowany .class o nazwie ClassName $ 1.class lub ClassName $ 1 $ 1.class .

Te przypadki są pochodnymi mojej inspekcji plików .class w jar.

SGuru
źródło
Mam klasę, która nie spełnia żadnego z tych kryteriów, a class.getName () nadal jest błędne - dla Group.java zwraca Group _ $$ _ jvst248_20. Nie mam pojęcia, co się dzieje. Zdecydowanie bez wyliczeń, rozszerzeń ani implementacji.
Amalgovinus
0

Odpowiadając na twój komentarz, są złe zajęcia anonimowe. Z całą pewnością nie. Rozważ to, aby przypisać detektor akcji do JButton:

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

lub to zrobić sortowanie bez rozróżniania wielkości liter według właściwości "name"

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

Zobaczysz także wiele klas Runnable i Calllable wykonanych jako klasy anonimowe.

Matt
źródło