Bagaimana seseorang bisa mendapatkan nama kelas dari metode statis di kelas itu. Sebagai contoh
public class MyClass {
public static String getClassName() {
String name = ????; // what goes here so the string "MyClass" is returned
return name;
}
}
Singkatnya, saya sebenarnya ingin mengembalikan nama kelas sebagai bagian dari pesan dalam pengecualian.
try{ throw new RuntimeEsception();} catch(RuntimeEcxeption e){return e.getstackTrace()[1].getClassName();
}Jawaban:
Untuk mendukung refactoring dengan benar (ganti nama kelas), maka Anda harus menggunakan:
atau (terima kasih kepada @James Van Huis ):
sumber
Lakukan apa yang dikatakan toolkit. Jangan melakukan hal seperti ini:
sumber
getClass
mengembalikan tipe runtime, jadi tidak bisa statis.Di Java 7+ Anda dapat melakukan ini dalam metode / bidang statis:
sumber
Reflection.getCallerClass()
. Tapi itu memberi peringatan tentang berada di paket 'matahari'. Jadi ini mungkin solusi yang lebih baik.Reflection.getCallerClass()
. Ini agak rumit untuk operasi sepele nya, yaituOptional<Class<?>> myself = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) .walk(s -> s.map(StackWalker.StackFrame::getDeclaringClass) .findFirst());
, tetapi tentu saja, itu terhubung dengan fakta bahwa itu akan jauh lebih kuat.Jadi, kita memiliki situasi ketika kita perlu secara statis mendapatkan objek kelas atau nama lengkap / kelas sederhana tanpa penggunaan
MyClass.class
sintaks yang eksplisit .Ini bisa sangat berguna dalam beberapa kasus, misalnya contoh logger untuk kotlin fungsi tingkat atas (dalam hal ini kotlin membuat kelas Java statis yang tidak dapat diakses dari kode kotlin).
Kami memiliki beberapa varian berbeda untuk mendapatkan informasi ini:
new Object(){}.getClass().getEnclosingClass();
dicatat oleh Tom Hawtin - tackline
getClassContext()[0].getName();
dari yangSecurityManager
dicatat oleh Christoffer
new Throwable().getStackTrace()[0].getClassName();
menurut hitungan ludwig
Thread.currentThread().getStackTrace()[1].getClassName();
dari Keksi
dan akhirnya dahsyat
MethodHandles.lookup().lookupClass();
dari Rein
Saya sudah menyiapkan jmh tolok ukur untuk semua varian dan hasil adalah:
Kesimpulan
Hanya tersedia sejak Java 7 dan Android API 26!
Jika Anda membutuhkannya di banyak tempat dan tidak ingin kode byte Anda kembung karena banyak kelas anonim -
SecurityManager
adalah teman Anda (opsi terbaik ketiga).Tapi Anda tidak bisa begitu saja menelepon
getClassContext()
- itu dilindungi diSecurityManager
kelas. Anda membutuhkan beberapa kelas pembantu seperti ini:getStackTrace()
dari atau dariThread.currentThread()
. Sangat tidak efisien dan hanya dapat mengembalikan nama kelas sebagaiString
, bukanClass<*>
turunannya.PS
Jika Anda ingin membuat instance logger untuk utilitas kotlin statis (seperti saya :), Anda dapat menggunakan bantuan ini:
Contoh penggunaan:
sumber
Instruksi ini berfungsi dengan baik:
sumber
Thread.getStackTrace()
Anda akan melihat bahwa itu tidak melakukan apa-apa selainreturn (new Exception()).getStackTrace();
dalam kasus dipanggil padacurrentThread()
. Jadi solusi @count ludwig adalah cara yang lebih langsung untuk mencapai hal yang sama.Anda dapat melakukan sesuatu yang sangat manis dengan menggunakan JNI seperti ini:
MyObject.java:
kemudian:
kemudian:
MyObject.c:
Kemudian kompilasi C menjadi perpustakaan bersama yang disebut
libclassname.so
dan jalankan java!*tertawa kecil
sumber
Java_MyObject_getClassName
memiliki nama yang disematkan. Cara mengatasinya adalah dengan menggunakan JNIRegisterNatives
. Tentu saja Anda harus memberi makan itu dengan JNIFindClass(env, 'com/example/MyObject')
, jadi tidak ada kemenangan di sana juga.private static final String TAG = "MyClass"
atau yangprivate static final String TAG = MyClass.class.getSimpleName();
kedua lebih ramah untuk penggantian nama kelas global menggunakan IDE.Saya menggunakan ini untuk init Log4j Logger di bagian atas kelas saya (atau membubuhi keterangan).
PRO: Throwable sudah dimuat dan Anda dapat menghemat sumber daya dengan tidak menggunakan SecurityManager "IO heavy".
CON: Beberapa pertanyaan apakah ini akan bekerja untuk semua JVM.
sumber
Pelanggaran Manajer Keamanan
Atau, jika tidak disetel, gunakan kelas dalam yang memperluasnya (contoh di bawah ini disalin secara memalukan dari Real's HowTo ):
sumber
Jika Anda ingin seluruh nama paket bersamanya, hubungi:
Jika Anda hanya menginginkan elemen terakhir, hubungi:
sumber
Penggunaan kelas penelepon secara verbal seperti yang
MyClass.class.getName()
sebenarnya dilakukan, tetapi cenderung untuk menyalin / menempel kesalahan jika Anda menyebarkan kode ini ke banyak kelas / subkelas di mana Anda memerlukan nama kelas ini.Dan resep Tom Hawtin sebenarnya tidak buruk, kita hanya perlu memasaknya dengan cara yang benar :)
Jika Anda memiliki kelas dasar dengan metode statis yang dapat dipanggil dari subclass, dan metode statis ini perlu mengetahui kelas penelepon yang sebenarnya, ini dapat dicapai seperti berikut:
sumber
Solusi yang aman untuk refactoring, cut & paste-safe yang menghindari definisi kelas ad-hoc di bawah ini.
Tulis metode statis yang memulihkan nama kelas dengan hati-hati untuk memasukkan nama kelas dalam nama metode:
lalu ingat dalam metode statis Anda:
Keamanan refactoring diberikan dengan menghindari penggunaan string, keamanan cut & paste diberikan karena jika Anda memotong & menempelkan metode pemanggil Anda tidak akan menemukan getMyClassName () di kelas "MyClass2" target, sehingga Anda akan dipaksa untuk mendefinisikan ulang dan memperbaruinya.
sumber
Karena pertanyaannya Sesuatu seperti `this.class` bukan` ClassName.class`? ditandai sebagai duplikat untuk yang ini (yang dapat diperdebatkan karena pertanyaan itu adalah tentang kelas daripada nama kelas), saya memposting jawabannya di sini:
Penting untuk didefinisikan
thisClass
sebagai pribadi karena:1) itu tidak boleh diwarisi: kelas turunan harus mendefinisikan sendiri
thisClass
atau menghasilkan pesan kesalahan2) referensi dari kelas lain harus dilakukan
ClassName.class
daripadaClassName.thisClass
.Dengan
thisClass
ditentukan, akses ke nama kelas menjadi:sumber
Saya membutuhkan nama kelas dalam metode statis beberapa kelas jadi saya menerapkan JavaUtil Class dengan metode berikut:
Semoga ini bisa membantu!
sumber
Saya telah menggunakan dua pendekatan ini untuk keduanya
static
dannon static
skenario:Kelas utama:
Cara memberikan nama kelas:
cara non statis:
Cara statis:
sumber
Jika Anda menggunakan refleksi, Anda bisa mendapatkan objek Metode dan kemudian:
Untuk mendapatkan Metode itu sendiri, Anda mungkin dapat menggunakan:
sumber
Class.forName("class name")
memberi Anda kelas. Mengapa Anda ingin mengambilnya melalui Metode?