Č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.