Що таке синтетичний клас на Java? Навіщо його використовувати? Як я можу ним користуватися?
Що таке синтетичний клас на Java? Навіщо його використовувати? Як я можу ним користуватися?
Відповіді:
Наприклад, коли у вас є оператор переключення, java створює змінну, яка починається з $. Якщо ви хочете побачити приклад цього, загляньте в java-відображення класу, який має в ньому оператор переключення. Ви побачите ці змінні, коли у вас буде принаймні один оператор переключення в будь-якому місці класу.
Щоб відповісти на ваше запитання, я не вважаю, що ви можете отримати доступ (крім рефлексії) до синтетичних класів.
Якщо ви аналізуєте клас, про який ви нічого не знаєте (за допомогою рефлексії), і вам потрібно знати дуже конкретні та низькорівневі речі про цей клас, ви можете в кінцевому підсумку використовувати методи відображення Java, що стосуються синтетичних класів. Єдине "використання" тут - отримати більше інформації про клас для того, щоб правильно його використовувати у своєму коді.
(Якщо ви робите це, ви, ймовірно, будуєте рамки деяких видів, які могли використовувати інші розробники.)
В іншому випадку, якщо ви не використовуєте рефлексію, не існує практичного використання синтетичних класів, про які я знаю.
Java має можливість створювати класи під час виконання. Ці класи відомі як синтетичні класи або динамічні проксі.
Див. Http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html для отримання додаткової інформації.
Інші бібліотеки з відкритим кодом, такі як CGLIB та ASM, також дозволяють генерувати синтетичні класи та є більш потужними, ніж бібліотеки, що надаються JRE.
Синтетичні класи використовуються бібліотеками AOP (Aspect-орієнтоване програмування), такими як Spring AOP та AspectJ, а також бібліотеками ORM, такими як Hibernate.
Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
java.lang.reflect.Member#isSynthetic
каже: Повертає істину, якщо цей член був введений компілятором; повертає помилку в іншому випадку.
java.lang.reflect.Member#isSynthetic
не має значення для початкового питання. Учасники поля, конструктори та методи. Оригінальне питання стосувалося синтетичних класів , а не синтетичних членів. У Java 8 лямбда-вирази породжують синтетичні класи - я не впевнений, які інші обставини вони можуть виникнути.
синтетичні класи / методи / поля:
Ці речі важливі для ВМ. Перегляньте наступний фрагмент коду:
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() {
}
}
}
Відповідно до цього обговорення , хоча мовна специфікація описує "isSynthetic" властивість для класів, це в значній мірі ігнорується реалізаціями і не використовується ні для динамічних проксі, ні для анонімних класів. Синтетичні поля та конструктори використовуються для реалізації вкладених класів (немає поняття вкладених класів у байт-коді, лише у вихідному коді).
Я думаю, що поняття синтетичних класів просто виявилося не корисним, тобто нікого не цікавить, чи клас синтетичний. З полями та методами він, ймовірно, використовується саме в одному місці: щоб визначити, що відображатимуться у вигляді структури класів IDE - ви хочете, щоб там відображалися звичайні методи та поля, але не синтетичні, які використовуються для імітації вкладених класів. ОТО, ви хочете, щоб там з’являлися анонімні заняття.
Вони створюються JVM під час виконання, коли вони викликають приватних членів внутрішнього класу з метою налагодження
Методи, поля, клас, створений JVM під час виконання для його виконання, називаються Synthetic
http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html
http://javapapers.com/core-java/java-synthetic-class-method-field/
Також синтетичні класи або динамічні проксі використовуються EasyMock для створення реалізацій інтерфейсів або абстрактних класів під час виконання.
Коли компілятор Java компілює певні конструкції, наприклад внутрішні класи, він створює синтетичні конструкції ; це класи, методи, поля та інші конструкції, які не мають відповідної конструкції у вихідному коді.
Використання:
синтетичні конструкції дозволяють компіляторам Java реалізовувати нові функції мови Java без змін у JVM. Однак синтетичні конструкції можуть відрізнятися між різними реалізаціями компілятора Java, а це означає, що файли .class також можуть відрізнятися між різними реалізаціями.
довідка: docs.oracle.com
Як вже було зазначено в різних відповідях, компілятору дозволено генерувати різні конструкції (включаючи класи), які безпосередньо не відповідають чомусь у коді souce. Вони повинні бути позначені як синтетичні:
Бінарне представлення для класу чи інтерфейсу повинно також містити все наступне:
[...]
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. Оцінка часу виконання методичних посилань ).
Оскільки цей клас прямо не згадується ніде у вихідному коді, він повинен бути синтетичним.
Якщо я правильно це розумію, синтетичний клас - це такий, що генерується на льоту, без того, щоб давати йому явну назву. Наприклад:
//...
Thread myThread = new Thread() {
public void run() {
// do something ...
}
};
myThread.start();
//...
Це створює синтетичний підклас Thread і переосмислює його метод run (), потім інстанціює його і запускає.
Outer$1.class
.
Синтетичний клас не відображається у вашому коді: він складається компілятором. Наприклад, метод моста, складений компілятором у 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
Це склав компілятор; він не відображається у вашому коді.
Що таке синтетичний клас на Java?
synthetic
Клас являє собою .class
файл , створений з допомогою Java - компілятора і не існує в вихідному коді.
Приклад використання synthetic
класу: Анонімний внутрішній клас
synthetic
клас, і це анонімний внутрішній клас всередині java.text.DigitListDigitList$1.java
але це внутрішній файл вDigitList.java
Навіщо його використовувати?
Це механізм всередині логіки компілятора Java для створення .class
файлу
Як я можу ним користуватися?
Ні, розробники НЕ використовують це безпосередньо.
Компілятор Java використовує synthetic
для створення .class
файлу, а потім JVM зчитує .class
файл для виконання логіки програми.
Синтетичні конструкції - це класи, методи, поля тощо, які не мають відповідної конструкції у вихідному коді. Синтетичні конструкції дозволяють компіляторам Java реалізовувати нові функції мови Java без змін у JVM. Однак синтетичні конструкції можуть відрізнятися між різними реалізаціями компілятора Java, а це означає, що файли .class також можуть відрізнятися між різними реалізаціями.