Lese verdien av ‘private’ felt fra en annen klasse i Java

1. Oversikt

I denne raske opplæringen vil vi diskutere hvordan vi kan få tilgang til verdien av en privat felt fra en annen klasse i Java.

Før vi begynner med opplæringen, må vi forstå at privat tilgangsmodifikator forhindrer utilsiktet misbruk av felt. Men hvis vi ønsker å få tilgang til dem, kan vi gjøre det ved å bruke Reflection API.

2. Eksempel

La oss definere en prøveklasse Person med noe privat Enger:

offentlig klasse Person {private String name = "John"; privat byte alder = 30; privat kort uidNumber = 5555; privat int pinCode = 452002; privat lang kontaktNummer = 123456789L; privat flytehøyde = 6.1242f; privat dobbeltvekt = 75,2564; privat røye kjønn = 'M'; privat boolsk aktiv = sann; // getters og setters}

3. Å lage privat Felt tilgjengelig

Å lage noen privat felt tilgjengelig, vi må kalle Felt # settTilgjengelig metode:

Personperson = ny person (); FeltnavnFelt = person.getClass (). GetDeclaredField ("navn"); nameField.setAccessible (true);

I eksemplet ovenfor spesifiserer vi først feltet vi vil hente - Navn - ved å bruke Klasse # getDeclaredField metode. Deretter gjør vi feltet tilgjengelig ved hjelp av nameField.setAccessible (true).

4. Tilgang privat Primitive felt

Vi kan få tilgang til privat felt som er primitive ved å bruke Felt # getXxx metoder.

4.1. Få tilgang til heltallfelt

Vi kan bruke getByte,getShort, fårInt, og fåLang metoder for å få tilgang til byte,kort, int, og lang felt, henholdsvis:

@Test offentlig ugyldig nårGetIntegerFields_thenSuccess () kaster unntak {Person person = new Person (); Field ageField = person.getClass (). GetDeclaredField ("age"); ageField.setAccessible (true); byte alder = ageField.getByte (person); Assertions.assertEquals (30, alder); Felt uidNumberField = person.getClass (). GetDeclaredField ("uidNumber"); uidNumberField.setAccessible (true); kort uidNumber = uidNumberField.getShort (person); Assertions.assertEquals (5555, uidNumber); Felt pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (true); int pinCode = pinCodeField.getInt (person); Assertions.assertEquals (452002, pinCode); Felt contactNumberField = person.getClass (). GetDeclaredField ("contactNumber"); contactNumberField.setAccessible (true); lang contactNumber = contactNumberField.getLong (person); Assertions.assertEquals (123456789L, contactNumber); }

Det er også mulig å utføre autoboksing med primitive typer:

@Test offentlig ugyldig nårDoAutoboxing_thenSuccess () kaster Unntak {Person person = new Person (); Felt pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (true); Heltall pinCode = pinCodeField.getInt (person); Assertions.assertEquals (452002, pinCode); }

De getXxx metoder for primitive datatyper støtter også utvidelse:

@Test offentlig ugyldig nårDoWidening_thenSuccess () kaster Unntak {Person person = new Person (); Felt pinCodeField = person.getClass (). GetDeclaredField ("pinCode"); pinCodeField.setAccessible (true); Lang pinCode = pinCodeField.getLong (person); Assertions.assertEquals (452002L, pinCode); }

4.2. Få tilgang til flytende typefelt

Å få tilgang flyte og dobbelt felt, må vi bruke getFloat og getDouble metoder, henholdsvis:

@Test offentlig ugyldig nårGetFloatingTypeFields_thenSuccess () kaster Unntak {Person person = new Person (); Field heightField = person.getClass (). GetDeclaredField ("høyde"); heightField.setAccessible (true); flytehøyde = høydeFelt.getFloat (person); Assertions.assertEquals (6.1242f, høyde); Field weightField = person.getClass (). GetDeclaredField ("vekt"); weightField.setAccessible (true); dobbel vekt = weightField.getDouble (person); Assertions.assertEquals (75.2564, vekt); }

4.3. Få tilgang til tegnfelter

For å få tilgang til røye felt, kan vi bruke getChar metode:

@Test offentlig ugyldig nårGetCharacterFields_thenSuccess () kaster Unntak {Person person = new Person (); Felt genderField = person.getClass (). GetDeclaredField ("kjønn"); genderField.setAccessible (true); char kjønn = genderField.getChar (person); Assertions.assertEquals ('M', kjønn); }

4.4. Tilgang til boolske felt

På samme måte kan vi bruke getBoolean metoden for å få tilgang til boolsk felt:

@Test offentlig ugyldig nårGetBooleanFields_thenSuccess () kaster unntak {Person person = new Person (); Felt activeField = person.getClass (). GetDeclaredField ("aktiv"); activeField.setAccessible (true); boolsk aktiv = activeField.getBoolean (person); Assertions.assertTrue (aktiv); }

5. Tilgang privat Felter som er gjenstander

Vi kan få tilgang til privat felt som er objekter ved hjelp av Felt # få metode. Det er å merke seg at generisk metode returnerer en Gjenstand, så vi må kaste den til måltypen for å bruke verdien:

@Test offentlig ugyldig nårGetObjectFields_thenSuccess () kaster Unntak {Person person = new Person (); FeltnavnFelt = person.getClass (). GetDeclaredField ("navn"); nameField.setAccessible (true); String name = (String) nameField.get (person); Assertions.assertEquals ("John", navn); }

6. Unntak

La oss nå diskutere unntakene som JVM kan kaste mens de får tilgang til privat Enger.

6.1. IllegalArgumentException

JVM vil kaste IllegalArgumentExceptionhvis vi bruker en getXxx accessor som er inkompatibel med målfeltets type. I vårt eksempel, hvis vi skriver nameField.getInt (person), JVM kaster dette unntaket siden feltet er av type String og ikke int eller Heltall:

@Test offentlig ugyldighet givenInt_whenSetStringField_thenIllegalArgumentException () kaster Unntak {Person person = ny Person (); FeltnavnFelt = person.getClass (). GetDeclaredField ("navn"); nameField.setAccessible (true); Assertions.assertThrows (IllegalArgumentException.class, () -> nameField.getInt (person)); }

Som vi allerede har sett, getXxx metoder støtter utvidelse for de primitive typene. Det er viktig å merke seg det vi må oppnå det riktige målet for utvidelse for å lykkes. Ellers kaster JVM en IllegalArgumentException:

@Test offentlig ugyldighet givenInt_whenGetLongField_thenIllegalArgumentException () kaster Unntak {Person person = new Person (); Felt contactNumberField = person.getClass (). GetDeclaredField ("contactNumber"); contactNumberField.setAccessible (true); Assertions.assertThrows (IllegalArgumentException.class, () -> contactNumberField.getInt (person)); }

6.2. IllegalAccessException

JVM vil kaste et IllegalAccessExceptionhvis vi prøver å få tilgang til et felt som ikke har tilgangsrettigheter. I eksemplet ovenfor, hvis vi ikke skriver utsagnet nameField.setAccessible (true), så kaster JVM unntaket:

@Test offentlig ugyldig nårFieldNotSetAccessible_thenIllegalAccessException () kaster Unntak {Person person = new Person (); FeltnavnFelt = person.getClass (). GetDeclaredField ("navn"); Assertions.assertThrows (IllegalAccessException.class, () -> nameField.get (person)); }

6.3. NoSuchFieldException

Hvis vi prøver å få tilgang til et felt som ikke eksisterer i Person klasse, så kunne JVM kaste NoSuchFieldException:

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

6.4. NullPointerException

Til slutt, som du forventer, kaster JVM en NullPointerExceptionhvis vi passerer feltnavnet som null:

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

7. Konklusjon

I denne opplæringen har vi sett hvordan vi kan få tilgang til privat felt i en klasse i en annen klasse. Vi har også sett unntakene som JVM kan kaste og hva som forårsaker dem.

Som alltid er den komplette koden for dette eksemplet tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found