Semua jawaban "tidak ada dalam kode Anda" sudah kedaluwarsa dengan Java 8, karena lambdas dapat diimplementasikan sebagai kelas sintetis (bukan anonim).
OrangeDog
Agar adil, lambda masih tidak "secara ketat" kelas yang didefinisikan secara eksplisit dalam kode Anda. Jadi, "tidak ada dalam kode Anda" masih valid. Kompiler menghasilkan kelas sintetis untuk Anda tanpa definisi eksplisit dalam kode Anda.
ManoDestra
Jawaban:
15
Sebagai contoh, Ketika Anda memiliki pernyataan switch, java membuat variabel yang dimulai dengan $. Jika Anda ingin melihat contoh ini, mengintip ke refleksi java dari kelas yang memiliki pernyataan switch di dalamnya. Anda akan melihat variabel-variabel ini ketika Anda memiliki setidaknya satu pernyataan switch di mana saja di kelas.
Untuk menjawab pertanyaan Anda, saya tidak percaya Anda dapat mengakses (selain refleksi) kelas sintetis.
Jika Anda menganalisis kelas yang tidak Anda ketahui (melalui refleksi) dan perlu mengetahui hal-hal yang sangat spesifik dan tingkat rendah tentang kelas itu, Anda mungkin berakhir menggunakan metode refleksi Java yang ada hubungannya dengan kelas sintetis. Satu-satunya "penggunaan" di sini adalah mendapatkan informasi lebih lanjut tentang kelas untuk menggunakannya secara tepat dalam kode Anda.
(Jika Anda melakukan ini, Anda mungkin sedang membangun semacam kerangka yang bisa digunakan pengembang lain.)
Kalau tidak, jika Anda tidak menggunakan refleksi, tidak ada kegunaan praktis dari kelas sintetis yang saya tahu.
Ya, kode sampel akan baik jika Anda dapat memberikan contoh /
nanofarad
36
Ini tidak menjawab pertanyaan.
Dawood ibn Kareem
Untuk case switch, saya tidak yakin apakah ini terjadi untuk setiap switch, tetapi saya telah mengamati ini untuk switch dengan enums; kompiler menghasilkan kelas anonim dengan bidang statis tunggal yang menyediakan pemetaan Enum.ordinal () -> 1, 2, 3 ... (jadi urutan tanpa celah), dan kemudian instruksi pencarian menjalankan switch pada urutan ini, tidak secara langsung tentang tata cara.
Radim Vansa
106
Java memiliki kemampuan untuk membuat kelas saat runtime. Kelas-kelas ini dikenal sebagai Kelas Sintetis atau Proxy Dinamis.
Pustaka sumber terbuka lainnya, seperti CGLIB dan ASM juga memungkinkan Anda untuk menghasilkan kelas sintetis, dan lebih kuat daripada perpustakaan yang disediakan dengan JRE.
Kelas sintetis digunakan oleh pustaka AOP (Aspect Oriented Programming) seperti Spring AOP dan AspectJ, serta pustaka ORM seperti Hibernate.
Proxy Dinamis bukan Kelas Sintetis. Bukti:Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
Miha_x64
3
Javadoc untuk java.lang.reflect.Member#isSyntheticmengatakan: Mengembalikan nilai true jika anggota ini diperkenalkan oleh kompiler; mengembalikan false jika tidak.
Guillaume Husta
Saya percaya bahwa javadoc untuk java.lang.reflect.Member#isSynthetictidak relevan dengan pertanyaan awal. Anggota adalah bidang, konstruktor dan metode. Pertanyaan aslinya adalah tentang kelas sintetis , bukan anggota sintetis. Di Jawa 8, ekspresi lambda memunculkan kelas sintetis - Saya tidak yakin keadaan apa yang bisa muncul.
Pater Jeremy Krieg
54
Yah saya menemukan jawaban untuk pertanyaan pertama di google:
Kelas dapat ditandai sebagai sintetis jika dihasilkan oleh kompiler, yaitu, itu tidak muncul dalam kode sumber.
Ini hanya definisi dasar tapi saya menemukannya di utas forum dan tidak ada penjelasan. Masih mencari yang lebih baik ...
Hal-hal ini penting untuk VM. Lihat cuplikan kode berikut:
classMyOuter{privateMyInner 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 =newMyInner();// The Compiler has to create a synthetic method// to doSomething on MyInner object because this// method is private.// --> synthetic "doSomething" method
inner.doSomething();}privateclassMyInner{// the inner class holds a syntetic ref_pointer to// the outer "parent" class// --> synthetic fieldprivateMyInner(){}privatevoid doSomething(){}}}
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, tidak, hanya metode pengakses sintetis.
Miha_x64
8
Menurut diskusi ini , meskipun spesifikasi bahasa menggambarkan proprty "isSynthetic" untuk kelas, ini cukup diabaikan oleh implementasi dan tidak digunakan untuk proxy dinamis atau kelas anonim. Bidang sintetik dan konstruktor digunakan untuk mengimplementasikan kelas bertingkat (tidak ada konsep kelas bertingkat dalam kode byte, hanya dalam kode sumber).
Saya pikir konsep kelas sintetis terbukti tidak berguna, yaitu tidak ada yang peduli apakah kelas sintetis. Dengan bidang dan metode, ini mungkin digunakan tepat di satu tempat: untuk menentukan apa yang akan ditampilkan dalam tampilan struktur kelas IDE - Anda ingin metode dan bidang normal muncul di sana, tetapi bukan yang sintetis yang digunakan untuk mensimulasikan kelas bersarang. OTOH, Anda TIDAK ingin kelas anonim muncul di sana.
Jawaban ini tampaknya sudah usang karena java 8 - lambdas dan referensi metode memanfaatkan fitur ini. Saya telah menambahkan jawaban yang menunjukkan bahwa
Hulk
7
Mereka dibuat oleh JVM pada saat run time ketika mereka memanggil anggota pribadi kelas dalam untuk tujuan debugging
Metode, bidang, kelas yang dibuat oleh JVM selama waktu berjalan untuk tujuan pelaksanaannya disebut Sintetis
Ketika kompiler Java mengkompilasi konstruksi tertentu, seperti kelas dalam, itu membuat konstruksi sintetis ; ini adalah kelas, metode, bidang, dan konstruk lain yang tidak memiliki konstruk yang sesuai dalam kode sumber. Penggunaan:
Konstruksi sintetik memungkinkan kompiler Java untuk mengimplementasikan fitur-fitur bahasa Java baru tanpa perubahan pada JVM. Namun, konstruksi sintetik dapat bervariasi di antara implementasi Java compiler yang berbeda, yang berarti bahwa file .class dapat bervariasi di antara implementasi yang berbeda juga. referensi: docs.oracle.com
Seperti yang telah ditunjukkan oleh berbagai jawaban, kompiler diperbolehkan untuk menghasilkan berbagai konstruk (termasuk kelas) yang tidak secara langsung berhubungan dengan sesuatu dalam kode sumber. Ini harus ditandai sebagai sintetis:
Representasi biner untuk kelas atau antarmuka juga harus mengandung semua hal berikut:
[...]
11. Sebuah konstruk yang dipancarkan oleh kompiler Java harus ditandai sebagai sintetis jika tidak sesuai dengan konstruk yang dinyatakan secara eksplisit atau implisit dalam kode sumber. , kecuali konstruk yang dipancarkan adalah metode inisialisasi kelas (JVMS §2.9).
[...]
Seperti yang ditunjukkan oleh @ Holger dalam komentar untuk pertanyaan lain, contoh yang relevan untuk konstruksi tersebut adalah objek Kelas yang mewakili referensi metode dan lambda:
Saya harus setuju dengan @KumarAbhinav. Tidak semua kelas batin anonim adalah sintetis. Lihat: xinotes.net/notes/note/1339
bvdb
Kelas dalam anonim tidak menghasilkan kelas sintetis pada Oracle JDK 1.8.0_45, mereka menghasilkan kelas non-sintetis terpisah dengan nama tipe Outer$1.class.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Kelas sintetis tidak muncul di kode Anda: itu dibuat oleh kompiler. Misalnya, metode jembatan yang dibuat oleh kompiler di java biasanya sintetis.
publicclassPair<T>{private T first;private T second;publicvoid setSecond(T newValue){
second = newValue;}}publicclassDateIntervalextendsPair<String>{publicvoid setSecond(String second){System.out.println("OK sub");}publicstaticvoid main(String[] args)throwsNoSuchFieldException,SecurityException{DateInterval interval =newDateInterval();Pair pair = interval;
pair.setSecond("string1");}}
Menggunakan perintah javap -verbose DateInterval, Anda dapat melihat metode jembatan:
Konstruk sintetik adalah kelas, metode, bidang dll yang tidak memiliki konstruk yang sesuai dalam kode sumber. Konstruksi sintetik memungkinkan kompiler Java untuk mengimplementasikan fitur-fitur bahasa Java baru tanpa perubahan pada JVM. Namun, konstruksi sintetik dapat bervariasi di antara implementasi Java compiler yang berbeda, yang berarti bahwa file .class dapat bervariasi di antara implementasi yang berbeda juga.
-1. Teks yang sama, kata demi kata, telah diposting dalam jawaban yang diberikan satu tahun sebelum Anda [ stackoverflow.com/a/24271953/1144395] , dan lebih jauh lagi, jawaban itu juga mengutip referensi resmi dari mana teks itu berasal, dan menyediakan format untuk memudahkan pembacaan . Tolong jangan rakus pertanyaan spam dengan jawaban duplikat jelas.
Jawaban:
Sebagai contoh, Ketika Anda memiliki pernyataan switch, java membuat variabel yang dimulai dengan $. Jika Anda ingin melihat contoh ini, mengintip ke refleksi java dari kelas yang memiliki pernyataan switch di dalamnya. Anda akan melihat variabel-variabel ini ketika Anda memiliki setidaknya satu pernyataan switch di mana saja di kelas.
Untuk menjawab pertanyaan Anda, saya tidak percaya Anda dapat mengakses (selain refleksi) kelas sintetis.
Jika Anda menganalisis kelas yang tidak Anda ketahui (melalui refleksi) dan perlu mengetahui hal-hal yang sangat spesifik dan tingkat rendah tentang kelas itu, Anda mungkin berakhir menggunakan metode refleksi Java yang ada hubungannya dengan kelas sintetis. Satu-satunya "penggunaan" di sini adalah mendapatkan informasi lebih lanjut tentang kelas untuk menggunakannya secara tepat dalam kode Anda.
(Jika Anda melakukan ini, Anda mungkin sedang membangun semacam kerangka yang bisa digunakan pengembang lain.)
Kalau tidak, jika Anda tidak menggunakan refleksi, tidak ada kegunaan praktis dari kelas sintetis yang saya tahu.
sumber
Java memiliki kemampuan untuk membuat kelas saat runtime. Kelas-kelas ini dikenal sebagai Kelas Sintetis atau Proxy Dinamis.
Lihat http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html untuk informasi lebih lanjut.
Pustaka sumber terbuka lainnya, seperti CGLIB dan ASM juga memungkinkan Anda untuk menghasilkan kelas sintetis, dan lebih kuat daripada perpustakaan yang disediakan dengan JRE.
Kelas sintetis digunakan oleh pustaka AOP (Aspect Oriented Programming) seperti Spring AOP dan AspectJ, serta pustaka ORM seperti Hibernate.
sumber
Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
java.lang.reflect.Member#isSynthetic
mengatakan: Mengembalikan nilai true jika anggota ini diperkenalkan oleh kompiler; mengembalikan false jika tidak.java.lang.reflect.Member#isSynthetic
tidak relevan dengan pertanyaan awal. Anggota adalah bidang, konstruktor dan metode. Pertanyaan aslinya adalah tentang kelas sintetis , bukan anggota sintetis. Di Jawa 8, ekspresi lambda memunculkan kelas sintetis - Saya tidak yakin keadaan apa yang bisa muncul.Yah saya menemukan jawaban untuk pertanyaan pertama di google:
Ini hanya definisi dasar tapi saya menemukannya di utas forum dan tidak ada penjelasan. Masih mencari yang lebih baik ...
sumber
kelas / metode / bidang sintetis:
Hal-hal ini penting untuk VM. Lihat cuplikan kode berikut:
sumber
Menurut diskusi ini , meskipun spesifikasi bahasa menggambarkan proprty "isSynthetic" untuk kelas, ini cukup diabaikan oleh implementasi dan tidak digunakan untuk proxy dinamis atau kelas anonim. Bidang sintetik dan konstruktor digunakan untuk mengimplementasikan kelas bertingkat (tidak ada konsep kelas bertingkat dalam kode byte, hanya dalam kode sumber).
Saya pikir konsep kelas sintetis terbukti tidak berguna, yaitu tidak ada yang peduli apakah kelas sintetis. Dengan bidang dan metode, ini mungkin digunakan tepat di satu tempat: untuk menentukan apa yang akan ditampilkan dalam tampilan struktur kelas IDE - Anda ingin metode dan bidang normal muncul di sana, tetapi bukan yang sintetis yang digunakan untuk mensimulasikan kelas bersarang. OTOH, Anda TIDAK ingin kelas anonim muncul di sana.
sumber
Mereka dibuat oleh JVM pada saat run time ketika mereka memanggil anggota pribadi kelas dalam untuk tujuan debugging
Metode, bidang, kelas yang dibuat oleh JVM selama waktu berjalan untuk tujuan pelaksanaannya disebut Sintetis
http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html
http://javapapers.com/core-java/java-synthetic-class-method-field/
sumber
Juga Kelas Sintetis atau Proxy Dinamis digunakan oleh EasyMock untuk membuat implementasi antarmuka atau kelas abstrak saat runtime.
http://www.easymock.org/
sumber
Ketika kompiler Java mengkompilasi konstruksi tertentu, seperti kelas dalam, itu membuat konstruksi sintetis ; ini adalah kelas, metode, bidang, dan konstruk lain yang tidak memiliki konstruk yang sesuai dalam kode sumber.
Penggunaan: Konstruksi sintetik memungkinkan kompiler Java untuk mengimplementasikan fitur-fitur bahasa Java baru tanpa perubahan pada JVM. Namun, konstruksi sintetik dapat bervariasi di antara implementasi Java compiler yang berbeda, yang berarti bahwa file .class dapat bervariasi di antara implementasi yang berbeda juga.
referensi: docs.oracle.com
sumber
Seperti yang telah ditunjukkan oleh berbagai jawaban, kompiler diperbolehkan untuk menghasilkan berbagai konstruk (termasuk kelas) yang tidak secara langsung berhubungan dengan sesuatu dalam kode sumber. Ini harus ditandai sebagai sintetis:
13.1. Bentuk Biner
Seperti yang ditunjukkan oleh @ Holger dalam komentar untuk pertanyaan lain, contoh yang relevan untuk konstruksi tersebut adalah objek Kelas yang mewakili referensi metode dan lambda:
Keluaran:
Meskipun ini tidak disebutkan secara eksplisit, ini mengikuti dari 15.27.4. Evaluasi Run-Time dari Ekspresi Lambda :
dan kata-kata yang hampir identik untuk referensi metode ( 15.13.3. Evaluasi Run-Time dari Metode Referensi ).
Karena kelas ini tidak disebutkan secara eksplisit di mana pun dalam kode sumber, itu harus sintetis.
sumber
Jika saya melakukannya dengan benar, kelas sintetis dihasilkan dengan cepat, tanpa harus memberikannya nama eksplisit. Sebagai contoh:
Ini membuat subclass sintetis dari Thread dan menimpa metode run (), lalu instantiate dan mulai.
sumber
Outer$1.class
.Kelas sintetis tidak muncul di kode Anda: itu dibuat oleh kompiler. Misalnya, metode jembatan yang dibuat oleh kompiler di java biasanya sintetis.
Menggunakan perintah
javap -verbose DateInterval
, Anda dapat melihat metode jembatan:Ini dibuat oleh kompiler; itu tidak muncul dalam kode Anda.
sumber
Sebuah
synthetic
kelas adalah.class
file yang dihasilkan oleh Java Compiler dan itu tidak ada dalam kode sumber.Contoh penggunaan
synthetic
kelas: Kelas batin anonimsynthetic
kelas dan itu adalah kelas batin anonim di dalam java.text.DigitListDigitList$1.java
tetapi itu adalah file dalamDigitList.java
Ini adalah mekanisme di dalam logika kompiler Java untuk menghasilkan
.class
fileTidak, pengembang TIDAK menggunakannya secara langsung.
Java compiler digunakan
synthetic
untuk menghasilkan.class
file, dan kemudian JVM membaca.class
file tersebut untuk menjalankan logika program.Keterangan lebih lanjut
synthetic
kelas secara detailsynthetic
pintu keluar kelas di JDKsumber
Konstruk sintetik adalah kelas, metode, bidang dll yang tidak memiliki konstruk yang sesuai dalam kode sumber. Konstruksi sintetik memungkinkan kompiler Java untuk mengimplementasikan fitur-fitur bahasa Java baru tanpa perubahan pada JVM. Namun, konstruksi sintetik dapat bervariasi di antara implementasi Java compiler yang berbeda, yang berarti bahwa file .class dapat bervariasi di antara implementasi yang berbeda juga.
sumber