Membaca Nilai Bidang 'pribadi' dari Kelas Berbeda di Jawa

1. Ikhtisar

Dalam tutorial singkat ini, kita akan membahas bagaimana kita dapat mengakses nilai bidang privat dari kelas yang berbeda di Java.

Sebelum memulai dengan tutorial, kita perlu memahami bahwa pengubah akses pribadi mencegah penyalahgunaan bidang yang tidak disengaja. Namun, jika kita ingin mengaksesnya, kita dapat melakukannya dengan menggunakan API Refleksi.

2. Contoh

Mari tentukan kelas sampel Orang dengan beberapa bidang pribadi :

public class Person { private String name = "John"; private byte age = 30; private short uidNumber = 5555; private int pinCode = 452002; private long contactNumber = 123456789L; private float height = 6.1242f; private double weight = 75.2564; private char gender = 'M'; private boolean active = true; // getters and setters }

3. Membuat Bidang Pribadi Dapat Diakses

Untuk membuat setiap bidang pribadi dapat diakses, kita harus memanggil metode Field # setAccessible :

Person person = new Person(); Field nameField = person.getClass().getDeclaredField("name"); nameField.setAccessible(true);

Dalam contoh di atas, pertama-tama kita menetapkan bidang yang ingin kita ambil - nama - dengan menggunakan metode Class # getDeclaredField . Kemudian kami membuat bidang dapat diakses menggunakan nameField.setAccessible (true) .

4. Mengakses Bidang Primitif pribadi

Kita dapat mengakses bidang privat yang primitif dengan menggunakan metode Field # getXxx .

4.1. Mengakses Bidang Integer

Kita dapat menggunakan metode getByte, getShort , getInt , dan getLong untuk mengakses kolom byte , short , int , dan long , masing-masing:

@Test public void whenGetIntegerFields_thenSuccess() throws Exception { Person person = new Person(); Field ageField = person.getClass().getDeclaredField("age"); ageField.setAccessible(true); byte age = ageField.getByte(person); Assertions.assertEquals(30, age); Field uidNumberField = person.getClass().getDeclaredField("uidNumber"); uidNumberField.setAccessible(true); short uidNumber = uidNumberField.getShort(person); Assertions.assertEquals(5555, uidNumber); Field pinCodeField = person.getClass().getDeclaredField("pinCode"); pinCodeField.setAccessible(true); int pinCode = pinCodeField.getInt(person); Assertions.assertEquals(452002, pinCode); Field contactNumberField = person.getClass().getDeclaredField("contactNumber"); contactNumberField.setAccessible(true); long contactNumber = contactNumberField.getLong(person); Assertions.assertEquals(123456789L, contactNumber); }

Anda juga dapat melakukan autoboxing dengan tipe primitif:

@Test public void whenDoAutoboxing_thenSuccess() throws Exception { Person person = new Person(); Field pinCodeField = person.getClass().getDeclaredField("pinCode"); pinCodeField.setAccessible(true); Integer pinCode = pinCodeField.getInt(person); Assertions.assertEquals(452002, pinCode); }

Metode getXxx untuk tipe data primitif juga mendukung pelebaran:

@Test public void whenDoWidening_thenSuccess() throws Exception { Person person = new Person(); Field pinCodeField = person.getClass().getDeclaredField("pinCode"); pinCodeField.setAccessible(true); Long pinCode = pinCodeField.getLong(person); Assertions.assertEquals(452002L, pinCode); }

4.2. Mengakses Bidang Jenis Mengambang

Untuk mengakses bidang float dan double , kita perlu menggunakan metode getFloat dan getDouble , masing-masing:

@Test public void whenGetFloatingTypeFields_thenSuccess() throws Exception { Person person = new Person(); Field heightField = person.getClass().getDeclaredField("height"); heightField.setAccessible(true); float height = heightField.getFloat(person); Assertions.assertEquals(6.1242f, height); Field weightField = person.getClass().getDeclaredField("weight"); weightField.setAccessible(true); double weight = weightField.getDouble(person); Assertions.assertEquals(75.2564, weight); }

4.3. Mengakses Bidang Karakter

Untuk mengakses kolom char , kita dapat menggunakan metode getChar :

@Test public void whenGetCharacterFields_thenSuccess() throws Exception { Person person = new Person(); Field genderField = person.getClass().getDeclaredField("gender"); genderField.setAccessible(true); char gender = genderField.getChar(person); Assertions.assertEquals('M', gender); }

4.4. Mengakses Bidang Boolean

Demikian pula, kita dapat menggunakan metode getBoolean untuk mengakses bidang boolean :

@Test public void whenGetBooleanFields_thenSuccess() throws Exception { Person person = new Person(); Field activeField = person.getClass().getDeclaredField("active"); activeField.setAccessible(true); boolean active = activeField.getBoolean(person); Assertions.assertTrue(active); }

5. Mengakses Bidang Pribadi Yang Merupakan Objek

Kita dapat mengakses swasta bidang yang objek dengan menggunakan Field No. get metode . Perlu diperhatikan bahwa metode get generik mengembalikan sebuah Objek , jadi kita perlu mentransmisikannya ke tipe target untuk menggunakan nilainya :

@Test public void whenGetObjectFields_thenSuccess() throws Exception { Person person = new Person(); Field nameField = person.getClass().getDeclaredField("name"); nameField.setAccessible(true); String name = (String) nameField.get(person); Assertions.assertEquals("John", name); }

6. Pengecualian

Sekarang, mari kita bahas pengecualian yang dapat dilakukan JVM saat mengakses bidang pribadi .

6.1. IllegalArgumentException

JVM akan menampilkan IllegalArgumentException jika kita menggunakan aksesor getXxx yang tidak kompatibel dengan jenis bidang target . Dalam contoh kita, jika kita menulis nameField.getInt (person) , JVM melontarkan pengecualian ini karena field berjenis String dan bukan int atau Integer :

@Test public void givenInt_whenSetStringField_thenIllegalArgumentException() throws Exception { Person person = new Person(); Field nameField = person.getClass().getDeclaredField("name"); nameField.setAccessible(true); Assertions.assertThrows(IllegalArgumentException.class, () -> nameField.getInt(person)); }

Seperti yang telah kita lihat, metode getXxx mendukung pelebaran untuk tipe primitif. Penting untuk dicatat bahwa kami perlu memberikan target yang benar agar pelebaran berhasil . Jika tidak, JVM akan menampilkan IllegalArgumentException :

@Test public void givenInt_whenGetLongField_thenIllegalArgumentException() throws Exception { Person person = new Person(); Field contactNumberField = person.getClass().getDeclaredField("contactNumber"); contactNumberField.setAccessible(true); Assertions.assertThrows(IllegalArgumentException.class, () -> contactNumberField.getInt(person)); }

6.2. IllegalAccessException

JVM akan memunculkan IllegalAccessException jika kita mencoba mengakses bidang yang tidak memiliki hak akses . Dalam contoh di atas, jika kita tidak menulis pernyataan nameField.setAccessible (true) , maka JVM akan menampilkan pengecualian:

@Test public void whenFieldNotSetAccessible_thenIllegalAccessException() throws Exception { Person person = new Person(); Field nameField = person.getClass().getDeclaredField("name"); Assertions.assertThrows(IllegalAccessException.class, () -> nameField.get(person)); }

6.3. NoSuchFieldException

Jika kami mencoba mengakses bidang yang tidak ada di kelas Person , maka JVM dapat menampilkan NoSuchFieldException :

Assertions.assertThrows(NoSuchFieldException.class, () -> person.getClass().getDeclaredField("firstName"));

6.4. NullPointerException

Terakhir, seperti yang Anda harapkan, JVM melontarkan NullPointerException jika kita meneruskan nama field sebagai null :

Assertions.assertThrows(NullPointerException.class, () -> person.getClass().getDeclaredField(null));

7. Kesimpulan

Dalam tutorial ini, kita telah melihat bagaimana kita dapat mengakses bidang privat kelas di kelas lain. Kami juga telah melihat pengecualian yang dapat dilemparkan JVM dan apa penyebabnya.

Seperti biasa, kode lengkap untuk contoh ini tersedia di GitHub.