Klasa syntetyczna w Javie


143

Co to jest klasa syntetyczna w Javie? Dlaczego warto go używać? Jak mogę tego używać?


1
Wszystkie odpowiedzi „nie w Twoim kodzie” są nieaktualne w Javie 8, ponieważ lambdy mogą być implementowane jako klasy syntetyczne (nie anonimowe).
OrangeDog

Szczerze mówiąc, lambda nadal nie jest „ściśle” klasą zdefiniowaną jawnie w kodzie. Zatem „nie w Twoim kodzie” jest nadal ważne. Kompilator generuje klasy syntetyczne bez jawnej definicji w kodzie.
ManoDestra

Odpowiedzi:


15

Na przykład, gdy masz instrukcję switch, java tworzy zmienną zaczynającą się od $. Jeśli chcesz zobaczyć przykład tego, zajrzyj do odbicia Java klasy, która zawiera instrukcję switch. Zobaczysz te zmienne, gdy masz co najmniej jedną instrukcję switch w dowolnym miejscu w klasie.

Odpowiadając na twoje pytanie, nie wierzę, że jesteś w stanie uzyskać dostęp (poza refleksją) do klas syntetycznych.

Jeśli analizujesz klasę, o której nic nie wiesz (poprzez refleksję) i potrzebujesz wiedzieć bardzo szczegółowe i niskopoziomowe informacje o tej klasie, możesz skończyć z wykorzystaniem metod odbicia Java, które mają do czynienia z klasami syntetycznymi. Jedynym „zastosowaniem” tutaj jest uzyskanie większej ilości informacji o klasie w celu odpowiedniego jej wykorzystania w kodzie.

(Jeśli to robisz, prawdopodobnie tworzysz pewnego rodzaju strukturę, z której mogliby korzystać inni programiści).

W przeciwnym razie, jeśli nie używasz refleksji, nie ma praktycznego zastosowania klas syntetycznych, o których wiem.


1
Tak, przykładowy kod byłby dobry, gdybyś mógł podać przykład /
nanofarad

36
To nie odpowiada na pytanie.
Dawood ibn Kareem

W przypadku przełącznika nie jestem pewien, czy dzieje się tak dla każdego przełącznika, ale zaobserwowałem to w przypadku przełącznika z wyliczeniami; kompilator generuje anonimową klasę z pojedynczym statycznym polem, które zapewnia mapowanie Enum.ordinal () -> 1, 2, 3 ... (czyli sekwencja bez przerw), a następnie instrukcja lookupswitch uruchamia przełącznik na tej sekwencji, a nie bezpośrednio na liczbach porządkowych.
Radim Vansa,

106

Java ma możliwość tworzenia klas w czasie wykonywania. Te klasy są znane jako klasy syntetyczne lub dynamiczne proxy.

Więcej informacji można znaleźć pod adresem http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html .

Inne biblioteki open source, takie jak CGLIB i ASM, również umożliwiają generowanie klas syntetycznych i mają większe możliwości niż biblioteki dostarczane ze środowiskiem JRE.

Klasy syntetyczne są używane przez biblioteki AOP (Aspect Oriented Programming), takie jak Spring AOP i AspectJ, a także biblioteki ORM, takie jak Hibernate.


6
Dynamiczne proxy nie są Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
klasami

3
Element javadoc for java.lang.reflect.Member#isSyntheticmówi: Zwraca wartość true, jeśli ten element członkowski został wprowadzony przez kompilator; w przeciwnym razie zwraca false.
Guillaume Husta

Uważam, że javadoc for java.lang.reflect.Member#isSyntheticnie ma związku z pierwotnym pytaniem. Członkami są pola, konstruktory i metody. Pierwotne pytanie dotyczyło klas syntetycznych , a nie syntetycznych członków. W Javie 8 wyrażenia lambda dają początek klasom syntetycznym - nie jestem pewien, jakie inne okoliczności mogą zaistnieć.
Ks. Jeremy Krieg

54

Dobrze znalazłem odpowiedź na pierwsze pytanie w google:

Klasa może być oznaczona jako syntetyczna, jeśli jest generowana przez kompilator, czyli nie pojawia się w kodzie źródłowym.

To tylko podstawowa definicja, ale znalazłem ją w wątku na forum i nie było żadnego wyjaśnienia. Wciąż szukam lepszego ...


15

syntetyczne klasy / metody / pola:

Te rzeczy są ważne dla maszyny wirtualnej. Spójrz na następujący fragment kodu:

class MyOuter {

  private MyInner inner;

  void createInner() {
    // The Compiler has to create a synthetic method
    // to construct a new MyInner because the constructor
    // is private.
    // --> synthetic "constructor" method
    inner = new MyInner();

    // The Compiler has to create a synthetic method
    // to doSomething on MyInner object because this
    // method is private.
    // --> synthetic "doSomething" method
    inner.doSomething();
  }

  private class MyInner {
    // the inner class holds a syntetic ref_pointer to
    // the outer "parent" class
    // --> synthetic field
    private MyInner() {
    }
    private void doSomething() {
    }
  }
}

2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, no, only syntetyczne metody pomocnicze.
Miha_x64

8

Zgodnie z tą dyskusją , chociaż specyfikacja języka opisuje właściwość „isSynthetic” dla klas, jest to prawie ignorowane przez implementacje i nie jest używane ani w przypadku dynamicznych serwerów proxy, ani klas anonimowych. Do implementacji klas zagnieżdżonych używa się pól syntetycznych i konstruktorów (nie ma koncepcji klas zagnieżdżonych w kodzie bajtowym, tylko w kodzie źródłowym).

Myślę, że koncepcja klas syntetycznych po prostu okazała się nieprzydatna, tj. Nikogo nie obchodzi, czy klasa jest syntetyczna. W przypadku pól i metod jest prawdopodobnie używany dokładnie w jednym miejscu: do określenia, co ma być wyświetlane w widoku struktury klas IDE - chcesz, aby pokazywały się tam zwykłe metody i pola, ale nie te syntetyczne używane do symulacji zagnieżdżonych klas. OTOH, CHCESZ, aby pokazywały się tam anonimowe zajęcia.


@OrangeDog: tak, to właśnie napisałem.
Michael Borgwardt

Ta odpowiedź wydaje się być przestarzała, ponieważ java 8 - lambdy i odwołania do metod wykorzystują tę funkcję. Dodałem odpowiedź, która to potwierdza
Hulk

7

Są tworzone przez maszynę JVM w czasie wykonywania, gdy wywołują prywatne elementy członkowskie klasy wewnętrznej w celu debugowania

Metody, pola i klasy utworzone przez maszynę JVM w czasie wykonywania w celu jej wykonania nazywane są syntetycznymi

http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html

http://javapapers.com/core-java/java-synthetic-class-method-field/


Myślę, że masz na myśli w czasie kompilacji, a nie w czasie wykonywania.
Mostowski Collapse

@sathis, czy chodziło Ci o javac, a nie o JVM?
Miha_x64


2

Kiedy kompilator Java kompiluje określone konstrukcje, takie jak klasy wewnętrzne, tworzy konstrukcje syntetyczne ; są to klasy, metody, pola i inne konstrukcje, które nie mają odpowiedniej konstrukcji w kodzie źródłowym.
Zastosowania: Konstrukcje syntetyczne umożliwiają kompilatorom języka Java wdrażanie nowych funkcji języka Java bez wprowadzania zmian w JVM. Jednak konstrukcje syntetyczne mogą się różnić w różnych implementacjach kompilatora Java, co oznacza, że ​​pliki .class mogą się różnić również w różnych implementacjach. źródło
: docs.oracle.com


2

Jak już wskazywały różne odpowiedzi, kompilator może generować różne konstrukcje (w tym klasy), które nie odpowiadają bezpośrednio czemuś w kodzie źródłowym. Muszą być oznaczone jako syntetyczne:

13.1. Forma binarna

Binarna reprezentacja klasy lub interfejsu musi również zawierać wszystkie następujące elementy:
[...]
11. Konstrukcja emitowana przez kompilator języka Java musi być oznaczona jako syntetyczna, jeśli nie odpowiada konstrukcji zadeklarowanej jawnie lub niejawnie w kodzie źródłowym , chyba że emitowana konstrukcja jest metodą inicjalizacji klasy (JVMS §2.9).
[…]

Jak zauważył @Holger w komentarzu do innego pytania, odpowiednimi przykładami takich konstrukcji są obiekty Class reprezentujące odwołania do metod i lambdy:

System.out.println(((Runnable) System.out::println).getClass().isSynthetic());
System.out.println(((Runnable) () -> {}).getClass().isSynthetic());

Wynik:

true
true

Chociaż nie jest to wyraźnie wymienione, wynika to z 15.27.4. Ocena wyrażeń lambda w czasie rzeczywistym :

Wartość wyrażenia lambda jest odwołaniem do wystąpienia klasy o następujących właściwościach: [...]

oraz prawie identyczne sformułowanie odniesień do metod ( 15.13.3. Ocena odniesień do metod w czasie wykonywania ).

Ponieważ ta klasa nie jest wyraźnie wymieniona w kodzie źródłowym, musi być syntetyczna.


1

Jeśli dobrze rozumiem, klasa syntetyczna to klasa generowana w locie, bez konieczności nadawania jej wyraźnej nazwy. Na przykład:

//...
Thread myThread = new Thread() {
         public void run() {
           // do something ...
         }
       };
myThread.start();
//...

Spowoduje to utworzenie syntetycznej podklasy Thread i nadpisanie jej metody run (), a następnie utworzenie jej wystąpienia i uruchomienie.


3
myślałem, że to anonimowa klasa wewnętrzna
Kumar Abhinav

2
Muszę się zgodzić z @KumarAbhinav. Nie wszystkie anonimowe klasy wewnętrzne są syntetyczne. Zobacz: xinotes.net/notes/note/1339
bvdb

Anonimowe klasy wewnętrzne nie generują klas syntetycznych w Oracle JDK 1.8.0_45, generują oddzielne niesyntetyczne klasy z nazwami typów Outer$1.class.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1

Co to jest klasa syntetyczna w Javie?

syntheticKlasa jest .classplik generowany przez Java Compiler i nie istnieje w kodzie źródłowym.

Przykładowe użycie syntheticklasy: Anonimowa klasa wewnętrzna

  • java.text.DigitList $ 1 to syntheticklasa i jest to anonimowa klasa wewnętrzna wewnątrz java.text.DigitList
  • I nie ma pliku z kodem źródłowym o nazwie jak, DigitList$1.javaale jest to plik wewnętrzny wDigitList.java

Dlaczego warto go używać?

Jest to mechanizm wewnątrz logiki kompilatora Java do generowania .classpliku

Jak mogę tego używać?

Nie, programiści NIE używają go bezpośrednio.

Kompilator Java służy syntheticdo generowania .classpliku, a następnie JVM odczytuje .classplik w celu wykonania logiki programu.

Więcej szczegółów


artykuł jest bardzo przydatny, dziękuję
JasonMing

0

Konstrukcje syntetyczne to klasy, metody, pola itp., Które nie mają odpowiedniej konstrukcji w kodzie źródłowym. Konstrukcje syntetyczne umożliwiają kompilatorom języka Java wdrażanie nowych funkcji języka Java bez wprowadzania zmian w JVM. Jednak konstrukcje syntetyczne mogą się różnić w różnych implementacjach kompilatora Java, co oznacza, że ​​pliki .class mogą się różnić również w różnych implementacjach.


1
-1. Ten sam tekst, dosłownie, został zamieszczony w odpowiedzi udzielonej rok wcześniej [ stackoverflow.com/a/24271953/1144395] , a ponadto ta odpowiedź dodatkowo zacytowała oficjalne odniesienie, z którego pochodzi tekst, i zapewniła formatowanie ułatwiające czytanie . Nie spamuj chciwie pytań z wyraźnie zduplikowanymi odpowiedziami.
naki

0

Klasa syntetyczna nie pojawia się w twoim kodzie: jest tworzona przez kompilator. Np. Metoda pomostowa utworzona przez kompilator w Javie jest zazwyczaj syntetyczna.

public class Pair<T> {
    private T first;
    private T second;
    public void setSecond(T newValue) {
        second = newValue;
    }
}


public class DateInterval extends Pair<String> {
    public void setSecond(String second) {
        System.out.println("OK sub");
    }

    public static void main(String[] args) throws NoSuchFieldException, SecurityException {
        DateInterval interval = new DateInterval();
        Pair pair = interval;
        pair.setSecond("string1");
    }
}

Za pomocą polecenia javap -verbose DateIntervalmożesz zobaczyć metodę mostu:

public void setSecond(java.lang.Object);
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC

Zostało to stworzone przez kompilator; nie pojawia się w Twoim kodzie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.