Синтетичний клас на Java


143

Що таке синтетичний клас на Java? Навіщо його використовувати? Як я можу ним користуватися?


1
Усі відповіді "не в коді" застаріли в Java 8, оскільки лямбда можна реалізувати як синтетичні (не анонімні) класи.
OrangeDog

Якщо чесно, лямбда все ще не є "строго" класом, визначеним явно у вашому коді. Отже, "не в коді" все ще діє. Компілятор генерує для вас синтетичні класи без явного визначення у вашому коді.
ManoDestra

Відповіді:


15

Наприклад, коли у вас є оператор переключення, java створює змінну, яка починається з $. Якщо ви хочете побачити приклад цього, загляньте в java-відображення класу, який має в ньому оператор переключення. Ви побачите ці змінні, коли у вас буде принаймні один оператор переключення в будь-якому місці класу.

Щоб відповісти на ваше запитання, я не вважаю, що ви можете отримати доступ (крім рефлексії) до синтетичних класів.

Якщо ви аналізуєте клас, про який ви нічого не знаєте (за допомогою рефлексії), і вам потрібно знати дуже конкретні та низькорівневі речі про цей клас, ви можете в кінцевому підсумку використовувати методи відображення Java, що стосуються синтетичних класів. Єдине "використання" тут - отримати більше інформації про клас для того, щоб правильно його використовувати у своєму коді.

(Якщо ви робите це, ви, ймовірно, будуєте рамки деяких видів, які могли використовувати інші розробники.)

В іншому випадку, якщо ви не використовуєте рефлексію, не існує практичного використання синтетичних класів, про які я знаю.


1
Так, зразок коду було б добре, якщо ви можете навести приклад /
nanofarad

36
Це не відповідає на запитання.
Dawood ibn Kareem

Що стосується вимикача, я не впевнений, що це відбувається для кожного перемикача, але я спостерігав це за перемикачем із перерахунками; компілятор генерує анонімний клас з єдиним статичним полем, яке забезпечує відображення Enum.ordinal () -> 1, 2, 3 ... (так що послідовність без пропусків), а потім команда lookupswitch запускає комутатор по цій послідовності, а не безпосередньо на ординарках.
Радім Ванса

106

Java має можливість створювати класи під час виконання. Ці класи відомі як синтетичні класи або динамічні проксі.

Див. Http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html для отримання додаткової інформації.

Інші бібліотеки з відкритим кодом, такі як CGLIB та ASM, також дозволяють генерувати синтетичні класи та є більш потужними, ніж бібліотеки, що надаються JRE.

Синтетичні класи використовуються бібліотеками AOP (Aspect-орієнтоване програмування), такими як Spring AOP та AspectJ, а також бібліотеками ORM, такими як Hibernate.


6
Динамічні проксі не є синтетичними Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
класами. Доказ

3
Javadoc for java.lang.reflect.Member#isSyntheticкаже: Повертає істину, якщо цей член був введений компілятором; повертає помилку в іншому випадку.
Гійом Хуста

Я вважаю, що javadoc for java.lang.reflect.Member#isSyntheticне має значення для початкового питання. Учасники поля, конструктори та методи. Оригінальне питання стосувалося синтетичних класів , а не синтетичних членів. У Java 8 лямбда-вирази породжують синтетичні класи - я не впевнений, які інші обставини вони можуть виникнути.
Отець Джеремі

54

Ну, я знайшов відповідь на перше запитання в Google:

Клас може бути позначений як синтетичний, якщо він генерується компілятором, тобто він не відображається у вихідному коді.

Це лише основне визначення, але я знайшов це у форумі, і пояснення не було. Ще шукаю кращого ...


15

синтетичні класи / методи / поля:

Ці речі важливі для ВМ. Перегляньте наступний фрагмент коду:

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 六四 事件 法轮功, ні, лише методи синтетичного аксесуара.
Miha_x64

8

Відповідно до цього обговорення , хоча мовна специфікація описує "isSynthetic" властивість для класів, це в значній мірі ігнорується реалізаціями і не використовується ні для динамічних проксі, ні для анонімних класів. Синтетичні поля та конструктори використовуються для реалізації вкладених класів (немає поняття вкладених класів у байт-коді, лише у вихідному коді).

Я думаю, що поняття синтетичних класів просто виявилося не корисним, тобто нікого не цікавить, чи клас синтетичний. З полями та методами він, ймовірно, використовується саме в одному місці: щоб визначити, що відображатимуться у вигляді структури класів IDE - ви хочете, щоб там відображалися звичайні методи та поля, але не синтетичні, які використовуються для імітації вкладених класів. ОТО, ви хочете, щоб там з’являлися анонімні заняття.


@OrangeDog: так, це я написав.
Майкл Боргвардт

Ця відповідь, здається, застаріла, оскільки java 8 - лямбда та посилання методів використовують цю функцію. Я додав відповідь, що демонструє це
Халк

7

Вони створюються JVM під час виконання, коли вони викликають приватних членів внутрішнього класу з метою налагодження

Методи, поля, клас, створений JVM під час виконання для його виконання, називаються Synthetic

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

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


Я думаю, ви маєте на увазі під час компіляції, а не під час виконання.
Mostowski Згорнутись

@sathis, ти мав на увазі javac, а не JVM?
Miha_x64

3

Також синтетичні класи або динамічні проксі використовуються EasyMock для створення реалізацій інтерфейсів або абстрактних класів під час виконання.

http://www.easymock.org/


2

Коли компілятор Java компілює певні конструкції, наприклад внутрішні класи, він створює синтетичні конструкції ; це класи, методи, поля та інші конструкції, які не мають відповідної конструкції у вихідному коді.
Використання: синтетичні конструкції дозволяють компіляторам Java реалізовувати нові функції мови Java без змін у JVM. Однак синтетичні конструкції можуть відрізнятися між різними реалізаціями компілятора Java, а це означає, що файли .class також можуть відрізнятися між різними реалізаціями.
довідка: docs.oracle.com


2

Як вже було зазначено в різних відповідях, компілятору дозволено генерувати різні конструкції (включаючи класи), які безпосередньо не відповідають чомусь у коді souce. Вони повинні бути позначені як синтетичні:

13.1. Форма бінарного

Бінарне представлення для класу чи інтерфейсу повинно також містити все наступне:
[...]
11. Конструкція, що випромінюється компілятором Java, повинна бути позначена як синтетична, якщо вона не відповідає конструкції, заявленій явно або неявно у вихідному коді , якщо випущена конструкція не є методом ініціалізації класів (JVMS §2.9).
[...]

Як вказував @Holger в коментарі до іншого питання, відповідними прикладами таких конструкцій є об'єкти Class, що представляють посилання методу та лямбда:

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

Вихід:

true
true

Хоча це прямо не зазначено, це випливає з 15.27.4. Оцінка часу виконання лямбда-виразів :

Значення лямбда-виразу - це посилання на екземпляр класу з такими властивостями: [...]

і майже однакове формулювання посилань на методи ( 15.13.3. Оцінка часу виконання методичних посилань ).

Оскільки цей клас прямо не згадується ніде у вихідному коді, він повинен бути синтетичним.


1

Якщо я правильно це розумію, синтетичний клас - це такий, що генерується на льоту, без того, щоб давати йому явну назву. Наприклад:

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

Це створює синтетичний підклас Thread і переосмислює його метод run (), потім інстанціює його і запускає.


3
Я думав, що це анонімний внутрішній клас
Кумар Абхінав

2
Я маю згоду з @KumarAbhinav. Не всі анонімні внутрішні класи є синтетичними. Дивіться: xinotes.net/notes/note/1339
bvdb

Анонімні внутрішні класи не генерують синтетичні класи на Oracle JDK 1.8.0_45, вони генерують окремі несинтетичні класи з іменами типу Outer$1.class.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1

Синтетичний клас не відображається у вашому коді: він складається компілятором. Наприклад, метод моста, складений компілятором у Java, зазвичай є синтетичним.

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");
    }
}

За допомогою команди javap -verbose DateIntervalви можете побачити метод мосту:

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

Це склав компілятор; він не відображається у вашому коді.


1

Що таке синтетичний клас на Java?

syntheticКлас являє собою .classфайл , створений з допомогою Java - компілятора і не існує в вихідному коді.

Приклад використання syntheticкласу: Анонімний внутрішній клас

  • java.text.DigitList $ 1 - це syntheticклас, і це анонімний внутрішній клас всередині java.text.DigitList
  • І не існує файлу вихідного коду з іменем типу, DigitList$1.javaале це внутрішній файл вDigitList.java

Навіщо його використовувати?

Це механізм всередині логіки компілятора Java для створення .classфайлу

Як я можу ним користуватися?

Ні, розробники НЕ використовують це безпосередньо.

Компілятор Java використовує syntheticдля створення .classфайлу, а потім JVM зчитує .classфайл для виконання логіки програми.

Детальніше

  • Ця статтяsynthetic детально пояснює клас
  • Це посилання перераховує всі syntheticвиходи класів у JDK

стаття дуже корисна, дякую
JasonMing

0

Синтетичні конструкції - це класи, методи, поля тощо, які не мають відповідної конструкції у вихідному коді. Синтетичні конструкції дозволяють компіляторам Java реалізовувати нові функції мови Java без змін у JVM. Однак синтетичні конструкції можуть відрізнятися між різними реалізаціями компілятора Java, а це означає, що файли .class також можуть відрізнятися між різними реалізаціями.


1
-1. Сам же текст, дослівно, був розміщений у відповіді, наданій за рік до вашого [ stackoverflow.com/a/24271953/1144395] , а далі ця відповідь додатково цитувала офіційну посилання, звідки походить текст, та надала форматування для легшого читання . Будь ласка, не жадібно спамуйте запитання з чітко повторюваними відповідями.
naki
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.