Menggunakan Java Reflection, apakah mungkin untuk mendapatkan nama variabel lokal? Misalnya, jika saya punya ini:
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();
apakah mungkin untuk mengimplementasikan metode yang dapat menemukan nama-nama variabel tersebut, seperti:
public void baz(Foo... foos)
{
for (Foo foo: foos) {
// Print the name of each foo - b, a, and r
System.out.println(***);
}
}
EDIT: Pertanyaan ini berbeda dari Apakah ada cara di Jawa untuk menemukan nama variabel yang dilewatkan ke fungsi? dalam hal itu lebih murni mengajukan pertanyaan tentang apakah seseorang dapat menggunakan refleksi untuk menentukan nama variabel lokal, sedangkan pertanyaan lain (termasuk jawaban yang diterima) lebih fokus pada pengujian nilai-nilai variabel.
java
reflection
David Koelle
sumber
sumber
Jawaban:
Pada Java 8, beberapa informasi nama variabel lokal tersedia melalui refleksi. Lihat bagian "Perbarui" di bawah ini.
Informasi lengkap sering disimpan dalam file kelas. Salah satu optimasi waktu kompilasi adalah untuk menghapusnya, menghemat ruang (dan menyediakan beberapa obsfuscation). Namun, ketika itu hadir, setiap metode memiliki atribut tabel variabel lokal yang mencantumkan jenis dan nama variabel lokal, dan berbagai instruksi di mana mereka berada dalam ruang lingkup.
Mungkin pustaka rekayasa kode-byte seperti ASM akan memungkinkan Anda untuk memeriksa informasi ini saat runtime. Satu-satunya tempat yang masuk akal yang dapat saya pikirkan untuk membutuhkan informasi ini adalah dalam alat pengembangan, dan karena itu teknik byte-code mungkin berguna untuk keperluan lain juga.
Pembaruan: Dukungan terbatas untuk ini ditambahkan ke Java 8. Nama parameter (kelas khusus variabel lokal) sekarang tersedia melalui refleksi. Di antara tujuan lain, ini dapat membantu mengganti
@ParameterName
anotasi yang digunakan oleh wadah injeksi ketergantungan.sumber
Itu tidak mungkin sama sekali. Nama variabel tidak dikomunikasikan dalam Java (dan mungkin juga dihapus karena optimisasi kompiler).
EDIT (terkait dengan komentar):
Jika Anda mundur dari gagasan harus menggunakannya sebagai parameter fungsi, berikut ini adalah alternatif (yang tidak akan saya gunakan - lihat di bawah):
Akan ada masalah jika
a == b, a == r, or b == r
atau ada bidang lain yang memiliki referensi yang sama.EDIT sekarang tidak perlu karena pertanyaan diklarifikasi
sumber
( Sunting: dua jawaban sebelumnya dihapus, satu untuk menjawab pertanyaan seperti yang berdiri sebelum pengeditan dan satu untuk menjadi, jika tidak sepenuhnya salah, setidaknya dekat dengan itu. )
Jika Anda mengompilasi dengan informasi debug pada (
javac -g
), nama-nama variabel lokal disimpan dalam file .class. Sebagai contoh, ambil kelas sederhana ini:Setelah dikompilasi dengan
javac -g:vars TestLocalVarNames.java
, nama-nama variabel lokal sekarang di file .class.javap
's-l
bendera ( 'Cetak nomor baris dan tabel variabel lokal') dapat menunjukkan kepada mereka.javap -l -c TestLocalVarNames
menunjukkan:Spesifikasi VM menjelaskan apa yang kami lihat di sini:
§4.7.9
LocalVariableTable
Atribut :The
LocalVariableTable
menyimpan nama dan jenis variabel dalam setiap slot, sehingga memungkinkan untuk mencocokkan mereka dengan bytecode. Ini adalah bagaimana para pengadu dapat melakukan "Mengevaluasi ekspresi".Seperti yang dikatakan erickson, tidak ada cara untuk mengakses tabel ini melalui refleksi normal. Jika Anda masih bertekad untuk melakukan ini, saya percaya Java Platform Debugger Architecture (JPDA) akan membantu (tapi saya tidak pernah menggunakannya sendiri).
sumber
javac
letakkan tabel variabel lokal di kelas untuk setiap metode untuk membantu debugging. Gunakan-l
opsijavap
untuk melihat tabel variabel lokal.javac -g:vars
untuk mendapatkannya. (Saya sudah berusaha untuk mengedit jawaban ini selama tiga jam terakhir, tapi seperti yang saya katakan koneksi jaringan saya mengalami masalah, yang membuatnya sulit untuk penelitian.)sumber
getDeclaredFields()
dapat digunakan jika Anda ingin nama bidang pribadi jugaAnda bisa melakukan ini:
sumber
Yang perlu Anda lakukan adalah membuat array bidang dan kemudian mengaturnya ke kelas yang Anda inginkan seperti yang ditunjukkan di bawah ini.
Sebagai contoh jika Anda melakukannya
kamu akan mendapatkan
sumber
perbarui jawaban @Marcel Jackwerth untuk umum.
dan hanya bekerja dengan atribut kelas, tidak bekerja dengan variabel metode.
sumber
lihat contoh ini:
sumber