Čitanje vrijednosti "privatnih" polja iz druge klase na Javi

1. Pregled

U ovom brzom vodiču razgovarat ćemo o tome kako možemo pristupiti vrijednosti a privatni polje iz druge klase na Javi.

Prije početka s vodičem, moramo shvatiti da privatni modifikator pristupa sprečava slučajnu zlouporabu polja. Međutim, ako im želimo pristupiti, to možemo učiniti pomoću Reflection API-ja.

2. Primjer

Definirajmo klasu uzorka Osoba s nekim privatni polja:

javna klasa Osoba {private String name = "John"; dob privatnog bajta = 30; privatni kratki uidNumber = 5555; privatni int pinCode = 452002; privatni dugi broj kontakta = 123456789L; visina privatnog plovka = 6.1242f; privatna dvostruka težina = 75,2564; privatni char rod = 'M'; privatna logička vrijednost active = true; // geteri i postavljači}

3. Izrada privatni Dostupna polja

Da bi bilo koji privatni dostupno na terenu, moramo nazvati Polje # setDostupno metoda:

Osoba osoba = nova osoba (); Ime poljaField = person.getClass (). GetDeclaredField ("ime"); nameField.setAccessible (true);

U gornjem primjeru prvo odredimo polje koje želimo dohvatiti - Ime - pomoću Klasa # getDeclaredField metoda. Tada polje činimo dostupnim pomoću nameField.setAccessible (true).

4. Pristup privatni Primitivna polja

Možemo pristupiti privatni polja koja su primitivna pomoću Polje # getXxx metode.

4.1. Pristup cjelovitim poljima

Možemo koristiti getByte,getShort, getInt, i getLong metode za pristup bajt,kratak, int, i dugo polja, odnosno:

@Test public void whenGetIntegerFields_thenSuccess () baca iznimku {Person person = new Person (); Polje ageField = person.getClass (). GetDeclaredField ("dob"); ageField.setAccessible (true); bajt age = ageField.getByte (osoba); Assertions.assertEquals (30, dob); Polje uidNumberField = person.getClass (). GetDeclaredField ("uidNumber"); uidNumberField.setAccessible (true); kratki uidNumber = uidNumberField.getShort (osoba); Assertions.assertEquals (5555, uidNumber); Polje pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (true); int pinCode = pinCodeField.getInt (osoba); Assertions.assertEquals (452002, pinCode); Polje contactNumberField = person.getClass (). GetDeclaredField ("contactNumber"); contactNumberField.setAccessible (true); long contactNumber = contactNumberField.getLong (osoba); Assertions.assertEquals (123456789L, kontaktNumber); }

Također je moguće izvesti automatsko boksanje s primitivnim vrstama:

@Test public void whenDoAutoboxing_thenSuccess () baca iznimku {Person person = new Person (); Polje pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (true); Cijeli broj pinCode = pinCodeField.getInt (osoba); Assertions.assertEquals (452002, pinCode); }

The getXxx metode za primitivne tipove podataka također podržavaju širenje:

@Test public void whenDoWidening_thenSuccess () baca iznimku {Person person = new Person (); Polje pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (true); Dugi pinCode = pinCodeField.getLong (osoba); Assertions.assertEquals (452002L, pinCode); }

4.2. Pristup poljima plutajućeg tipa

Pristupiti plutati i dvostruko polja, moramo koristiti getFloat i getDouble metode, odnosno:

@Test public void whenGetFloatingTypeFields_thenSuccess () baca iznimku {Person person = new Person (); Visina poljaField = person.getClass (). GetDeclaredField ("visina"); heightField.setAccessible (true); visina plovka = heightField.getFloat (osoba); Assertions.assertEquals (6.1242f, visina); Polje weightField = person.getClass (). GetDeclaredField ("težina"); weightField.setAccessible (true); dvostruka težina = weightField.getDouble (osoba); Assertions.assertEquals (75,2564, težina); }

4.3. Pristup poljima znakova

Za pristup ugljen polja, možemo koristiti getChar metoda:

@Test public void whenGetCharacterFields_thenSuccess () baca iznimku {Person person = new Person (); Polje genderField = person.getClass (). GetDeclaredField ("spol"); genderField.setAccessible (true); char spol = genderField.getChar (osoba); Assertions.assertEquals ('M', spol); }

4.4. Pristup logičkim poljima

Slično tome, možemo koristiti getBoolean metoda za pristup boolean polje:

@Test public void whenGetBooleanFields_thenSuccess () baca iznimku {Person person = new Person (); Polje activeField = person.getClass (). GetDeclaredField ("aktivno"); activeField.setAccessible (true); boolean active = activeField.getBoolean (osoba); Assertions.assertTrue (aktivno); }

5. Pristupanje privatni Polja koja su objekti

Možemo pristupiti privatni polja koja su objekti pomoću Polje # get metoda. Valja napomenuti da je generički dobiti metoda vraća an Objekt, pa ćemo ga morati prebaciti na ciljani tip da bismo iskoristili vrijednost:

@Test public void whenGetObjectFields_thenSuccess () baca iznimku {Person person = new Person (); Ime poljaField = person.getClass (). GetDeclaredField ("ime"); nameField.setAccessible (true); Ime niza = (Niz) nameField.get (osoba); Assertions.assertEquals ("Ivan", ime); }

6. Iznimke

Sada, razgovarajmo o iznimkama koje JVM može baciti dok pristupa privatni polja.

6.1. IlegalArgumentException

JVM će baciti IlegalArgumentExceptionako koristimo a getXxx pristupnik koji je nespojiv s vrstom ciljanog polja. U našem primjeru, ako napišemo nameField.getInt (osoba), JVM baca ovu iznimku jer je polje tipa Niz a ne int ili Cijeli broj:

@Test public void givenInt_whenSetStringField_thenIllegalArgumentException () baca iznimku {Person person = new Person (); Ime poljaField = person.getClass (). GetDeclaredField ("ime"); nameField.setAccessible (true); Assertions.assertThrows (IllegalArgumentException.class, () -> nameField.getInt (osoba)); }

Kao što smo već vidjeli, getXxx metode podržavaju širenje za primitivne tipove. Važno je to napomenuti moramo pružiti točnu metu za širenje kako bismo bili uspješni. Inače, JVM baca znak IlegalArgumentException:

@Test public void givenInt_whenGetLongField_thenIllegalArgumentException () baca izuzetak {Person person = new Person (); Polje contactNumberField = person.getClass (). GetDeclaredField ("contactNumber"); contactNumberField.setAccessible (true); Assertions.assertThrows (IllegalArgumentException.class, () -> contactNumberField.getInt (osoba)); }

6.2. IllegalAccessException

JVM će baciti IllegalAccessExceptionako pokušavamo pristupiti polju koje nema prava pristupa. U gornjem primjeru, ako ne napišemo izjavu nameField.setAccessible (true), tada JVM baca iznimku:

@Test public void whenFieldNotSetAccessible_thenIllegalAccessException () baca iznimku {Person person = new Person (); Ime poljaField = person.getClass (). GetDeclaredField ("ime"); Assertions.assertThrows (IllegalAccessException.class, () -> nameField.get (person)); }

6.3. NoSuchFieldException

Ako pokušamo pristupiti polju koje ne postoji u Osoba razreda, tada bi JVM mogao baciti NoSuchFieldException:

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

6.4. NullPointerException

Napokon, kao što ste očekivali, JVM baca a NullPointerExceptionako ime polja proslijedimo kao null:

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

7. Zaključak

U ovom uputstvu vidjeli smo kako možemo pristupiti privatni polja klase u drugom razredu. Vidjeli smo i iznimke koje JVM može baciti i što ih uzrokuje.

Kao i uvijek, cjeloviti kôd za ovaj primjer dostupan je na GitHub-u.