Di Jawa, apa perbedaan antara ini:
Object o1 = ....
o1.getClass().getSimpleName();
o1.getClass().getName();
o1.getClass().getCanonicalName();
Saya telah memeriksa Javadoc beberapa kali, namun ini tidak pernah menjelaskan dengan baik. Saya juga menjalankan tes dan itu tidak mencerminkan makna nyata di balik cara metode ini disebut.
Jawaban:
Jika Anda tidak yakin tentang sesuatu, cobalah menulis tes terlebih dahulu.
Saya melakukan ini:
Cetakan:
Ada entri kosong di blok terakhir tempat
getSimpleName
mengembalikan string kosong.Hasilnya melihat ini:
Class.forName
dengan defaultClassLoader
. Dalam ruang lingkup tertentuClassLoader
, semua kelas memiliki nama unik.toString
atau operasi logging. Ketikajavac
kompilator memiliki pandangan lengkap tentang classpath, ia menegakkan keunikan nama kanonik di dalamnya dengan berbenturan kelas dan nama paket yang sepenuhnya memenuhi syarat pada waktu kompilasi. Namun JVM harus menerima bentrokan nama tersebut, dan dengan demikian nama kanonik tidak secara unik mengidentifikasi kelas dalam aClassLoader
. (Jika dipikir-pikir, nama yang lebih baik untuk pengambil ini adalahgetJavaName
; tetapi metode ini berasal dari waktu ketika JVM digunakan hanya untuk menjalankan program Java.)toString
operasi penebangan atau tetapi tidak dijamin untuk menjadi unik.sumber
Menambahkan kelas lokal, lambdas dan
toString()
metode untuk melengkapi dua jawaban sebelumnya. Lebih lanjut, saya menambahkan array lambdas dan array kelas anonim (yang tidak masuk akal dalam praktiknya):Ini adalah hasil lengkapnya:
Jadi, inilah aturannya. Pertama, mari kita mulai dengan tipe primitif dan
void
:void
, keempat metode hanya mengembalikan namanya.Sekarang aturan untuk
getName()
metode ini:getName()
) yaitu nama paket diikuti dengan titik (jika ada paket ), diikuti dengan nama file kelasnya seperti yang dihasilkan oleh kompiler (tanpa akhiran.class
). Jika tidak ada paket, itu hanya nama file kelas. Jika kelas adalah kelas dalam, bersarang, lokal atau anonim, kompiler harus menghasilkan setidaknya satu$
dalam nama file kelasnya. Perhatikan bahwa untuk kelas anonim, nama kelas akan diakhiri dengan tanda dolar diikuti dengan angka.$$Lambda$
, diikuti oleh angka, diikuti oleh garis miring, diikuti oleh nomor lain.Z
untukboolean
,B
untukbyte
,S
untukshort
,C
untukchar
,I
untukint
,J
untuklong
,F
untukfloat
danD
untukdouble
. Untuk kelas dan antarmuka non-array deskriptor kelasL
diikuti oleh apa yang diberikan olehgetName()
diikuti oleh;
. Untuk kelas array, deskriptor kelas[
diikuti oleh deskriptor kelas dari tipe komponen (yang mungkin merupakan kelas array lain).getName()
metode mengembalikan deskriptor kelasnya. Aturan ini tampaknya gagal hanya untuk kelas array yang tipe komponennya adalah lambda (yang mungkin merupakan bug), tetapi mudah-mudahan ini seharusnya tidak menjadi masalah juga karena tidak ada titik bahkan pada keberadaan kelas array yang tipe komponennya adalah lambda.Sekarang,
toString()
metodenya:toString()
hasilnya kembali"interface " + getName()
. Jika itu primitif, ia akan kembali dengan sederhanagetName()
. Jika itu sesuatu yang lain (tipe kelas, bahkan jika itu cukup aneh), ia kembali"class " + getName()
.The
getCanonicalName()
Metode:getCanonicalName()
metode mengembalikan apa yanggetName()
dikembalikan metode.getCanonicalName()
kembali metodenull
untuk anonim atau kelas lokal dan untuk kelas array tersebut.getCanonicalName()
metode mengembalikan apagetName()
metode yang akan menggantikan tanda dolar yang diperkenalkan oleh kompiler oleh titik.getCanonicalName()
metode ini kembalinull
jika nama kanonik tipe komponennyanull
. Jika tidak, itu mengembalikan nama kanonik dari tipe komponen diikuti oleh[]
.The
getSimpleName()
Metode:getSimpleName()
mengembalikan nama kelas seperti yang tertulis dalam file sumber.getSimpleName()
mengembalikan sebuah kosongString
.getSimpleName()
hanya mengembalikan apa yanggetName()
akan kembali tanpa nama paket. Ini tidak masuk akal dan terlihat seperti bug bagi saya, tetapi tidak ada gunanya memanggilgetSimpleName()
kelas lambda untuk memulai.getSimpleName()
metode mengembalikan nama kelas komponen sederhana diikuti oleh[]
. Ini memiliki efek samping yang lucu / aneh yang dimiliki oleh kelas array yang jenis komponennya adalah kelas anonim[]
.sumber
… replacing the dollar-signs by dots
: Hanya tanda-tanda dolar yang diperkenalkan sebagai pembatas yang diganti. Anda dapat memiliki dolar sebagai bagian dari nama yang sederhana, dan itu akan tetap berlaku.Selain pengamatan Nick Holt, saya menjalankan beberapa kasus untuk
Array
tipe data:Cetakan snipet kode di atas:
sumber
Saya bingung dengan berbagai skema penamaan yang berbeda, dan baru saja akan bertanya dan menjawab pertanyaan saya sendiri ketika saya menemukan pertanyaan ini di sini. Saya pikir temuan saya cukup cocok, dan melengkapi apa yang sudah ada di sini. Fokus saya mencari dokumentasi tentang berbagai istilah, dan menambahkan beberapa istilah terkait lainnya yang mungkin muncul di tempat lain.
Perhatikan contoh berikut:
The nama yang sederhana dari
D
adalahD
. Itu hanya bagian yang Anda tulis ketika mendeklarasikan kelas. Kelas anonim tidak memiliki nama sederhana.Class.getSimpleName()
mengembalikan nama ini atau string kosong. Dimungkinkan untuk nama sederhana untuk memuat$
jika Anda menulisnya seperti ini, karena$
ini adalah bagian yang valid dari pengidentifikasi sesuai JLS bagian 3.8 (bahkan jika agak tidak disarankan).Menurut bagian JLS 6,7 , baik
a.b.C.D
dana.b.C.D.D.D
akan menjadi nama yang memenuhi syarat , tetapi hanyaa.b.C.D
akan menjadi nama kanonik dariD
. Jadi setiap nama kanonik adalah nama yang sepenuhnya memenuhi syarat, tetapi yang sebaliknya tidak selalu benar.Class.getCanonicalName()
akan mengembalikan nama kanonik ataunull
.Class.getName()
didokumentasikan untuk mengembalikan nama biner , sebagaimana ditentukan dalam bagian JLS 13.1 . Dalam hal ini ia mengembalikana.b.C$D
untukD
dan[La.b.C$D;
untukD[]
.Jawaban ini menunjukkan bahwa dimungkinkan bagi dua kelas yang dimuat oleh loader kelas yang sama untuk memiliki nama kanonik yang sama tetapi nama biner yang berbeda . Tidak ada nama yang cukup untuk menyimpulkan yang lain: jika Anda memiliki nama kanonik, Anda tidak tahu bagian mana dari nama itu adalah paket dan yang berisi kelas. Jika Anda memiliki nama biner, Anda tidak tahu mana
$
yang diperkenalkan sebagai pemisah dan yang merupakan bagian dari beberapa nama sederhana. (File kelas menyimpan nama biner dari kelas itu sendiri dan kelas terlampirnya , yang memungkinkan runtime untuk membuat perbedaan ini .)Kelas anonim dan kelas lokal tidak memiliki nama yang sepenuhnya memenuhi syarat tetapi masih memiliki nama biner . Hal yang sama berlaku untuk kelas yang bersarang di dalam kelas tersebut. Setiap kelas memiliki nama biner.
Berjalan
javap -v -private
padaa/b/C.class
menunjukkan bahwa bytecode merujuk pada tiped
asLa/b/C$D;
dan arrayds
sebagai[La/b/C$D;
. Ini disebut deskriptor , dan mereka ditentukan dalam bagian 4.3 JVMS .Nama kelas yang
a/b/C$D
digunakan dalam kedua deskriptor ini adalah apa yang Anda dapatkan dengan mengganti.
dengan/
nama biner. Spesifikasi JVM rupanya menyebut ini bentuk internal dari nama biner . JVMS bagian 4.2.1 menjelaskannya, dan menyatakan bahwa perbedaan dari nama biner adalah karena alasan historis.Nama file kelas di salah satu loader kelas berbasis nama file adalah apa yang Anda dapatkan jika Anda menginterpretasikannya
/
dalam bentuk internal nama biner sebagai pemisah direktori, dan menambahkan ekstensi nama file.class
ke dalamnya. Ini diselesaikan relatif terhadap jalur kelas yang digunakan oleh pemuat kelas yang dimaksud.sumber
ini adalah dokumen terbaik yang saya temukan menggambarkan getName (), getSimpleName (), getCanonicalName ()
https://javahowtodoit.wordpress.com/2014/09/09/java-lang-class-what-is-the-difference-between-class-getname-class-getcanonicalname-and-class-getsimplename/
sumber
Sangat menarik untuk dicatat
getCanonicalName()
dangetSimpleName()
dapat meningkatkanInternalError
ketika nama kelas salah. Ini terjadi untuk beberapa bahasa JVM non-Jawa, misalnya, Scala.Pertimbangkan yang berikut ini (Scala 2.11 di Java 8):
Ini bisa menjadi masalah untuk lingkungan bahasa campuran atau lingkungan yang secara dinamis memuat bytecode, misalnya, server aplikasi dan perangkat lunak platform lainnya.
sumber
getName () - mengembalikan nama entitas (kelas, antarmuka, kelas array, tipe primitif, atau batal) yang diwakili oleh objek Kelas ini, sebagai String.
getCanonicalName () - mengembalikan nama kanonik dari kelas dasar seperti yang didefinisikan oleh Spesifikasi Bahasa Jawa.
getSimpleName () - mengembalikan nama sederhana dari kelas yang mendasarinya, yaitu nama yang telah diberikan dalam kode sumber.
Satu perbedaan adalah bahwa jika Anda menggunakan kelas anonim Anda bisa mendapatkan nilai nol ketika mencoba untuk mendapatkan nama kelas menggunakan
getCanonicalName()
Fakta lain adalah bahwa
getName()
metode berperilaku berbeda darigetCanonicalName()
metode untuk kelas dalam .getName()
menggunakan dolar sebagai pemisah antara nama kanonik kelas terlampir dan nama sederhana kelas dalam.Untuk mengetahui lebih lanjut tentang mengambil nama kelas di Jawa .
sumber
sumber
Class<StringBuffer> clazz = StringBuffer.class