Vejledning til Java-refleksion

1. Oversigt

I denne artikel vil vi udforske Java-refleksion, som giver os mulighed for at inspicere eller modificere runtime-attributter for klasser, grænseflader, felter og metoder. Dette er især nyttigt, når vi ikke kender deres navne på kompileringstidspunktet.

Derudover kan vi instantiere nye objekter, påberåbe sig metoder og hente eller indstille feltværdier ved hjælp af refleksion.

2. Opsætning af projekt

For at bruge Java-refleksion behøver vi ikke medtage specielle krukker, enhver speciel konfiguration eller Maven-afhængigheder. JDK leveres med en gruppe klasser, der er samlet i java.lang.reflekteret pakke specielt til dette formål.

Så alt hvad vi skal gøre er at foretage følgende import i vores kode:

import java.lang.reflect. *;

og vi er gode til at gå.

For at få adgang til klasse-, metode- og feltoplysningerne for en forekomst, vi kalder getClass metode, som returnerer objektets runtime-klassrepræsentation. De returnerede klasse objekt giver metoder til at få adgang til information om en klasse.

3. Enkelt eksempel

For at få fødderne våde skal vi se på et meget grundlæggende eksempel, der inspicerer felterne i et simpelt Java-objekt ved kørsel.

Lad os oprette en simpel Person klasse med kun navn og alder felter og slet ingen metoder. Her er Person-klassen:

offentlig klasse person {privat strengnavn; privat int alder }

Vi bruger nu Java-refleksion til at finde navnene på alle felter i denne klasse. For at værdsætte kraften i refleksion konstruerer vi en Person objekt og brug Objekt som referencetype:

@Test offentlig ugyldighed givenObject_whenGetsFieldNamesAtRuntime_thenCorrect () {Objekt person = ny person (); Felt [] felter = person.getClass (). GetDeclaredFields (); Liste actualFieldNames = getFieldNames (felter); assertTrue (Arrays.asList ("name", "age") .containsAll (actualFieldNames)); }

Denne test viser os, at vi er i stand til at få en række Field genstande fra vores person objekt, selvom henvisningen til objektet er en overordnet type af det pågældende objekt.

I ovenstående eksempel var vi kun interesserede i navnene på disse felter, men der er meget mere, der kan gøres, og vi vil se flere eksempler på dette i de efterfølgende afsnit.

Bemærk hvordan vi bruger en hjælpermetode til at udtrække de faktiske feltnavne, det er en meget grundlæggende kode:

privat statisk liste getFieldNames (Field [] felter) {List fieldNames = new ArrayList (); til (Feltfelt: felter) fieldNames.add (field.getName ()); returner fieldNames; }

4. Brug af sager til Java-refleksion

Før vi går videre til de forskellige funktioner i Java-refleksion, vil vi diskutere nogle af de almindelige anvendelser, vi kan finde til det. Java-refleksion er ekstremt kraftfuld og kan komme meget praktisk på en række måder.

For eksempel har vi i mange tilfælde en navngivningskonvention for databasetabeller. Vi kan vælge at tilføje konsistens ved at forudindstille vores tabelnavne med tbl_, sådan at der kaldes til en tabel med elevdata tbl_student_data.

I sådanne tilfælde kan vi navngive Java-objektet, der indeholder elevdata som Studerende eller StudentData. Derefter bruger vi CRUD-paradigmet, har vi et indgangspunkt for hver operation, således at skab operationer modtager kun en Objekt parameter.

Vi bruger derefter refleksion til at hente objektnavnet og feltnavne. På dette tidspunkt kan vi kortlægge disse data til en DB-tabel og tildele objektfeltværdierne til de relevante DB-feltnavne.

5. Inspektion af Java-klasser

I dette afsnit vil vi undersøge den mest grundlæggende komponent i Java-refleksions-API'en. Java-klasseobjekter, som vi nævnte tidligere, giver os adgang til de interne detaljer i ethvert objekt.

Vi vil undersøge interne detaljer såsom et objekts klassenavn, modifikatorer, felter, metoder, implementerede grænseflader osv.

5.1. Gøre sig klar

For at få et godt greb om refleksions-API'en, som det anvendes på Java-klasser og har eksempler med variation, opretter vi et abstrakt Dyr klasse, der implementerer Spise interface. Denne grænseflade definerer spiseadfærd for enhver beton Dyr objekt, vi skaber.

Så for det første er her Spise grænseflade:

offentlig grænseflade Spise {String spiser (); }

og derefter betonen Dyr gennemførelse af Spise grænseflade:

offentlig abstrakt klasse Dyreudstyr Spise {offentlig statisk streng CATEGORY = "husholdning"; privat strengnavn; beskyttet abstrakt String getSound (); // konstruktør, standard getters og setters udeladt}

Lad os også oprette en anden grænseflade kaldet Bevægelse der beskriver, hvordan et dyr bevæger sig:

offentlig grænseflade Locomotion {String getLocomotion (); }

Vi opretter nu en betonklasse kaldet Ged som strækker sig Dyr og redskaber Bevægelse. Siden superklassen implementerer Spise, Ged bliver også nødt til at implementere grænseflades metoder:

offentlig klasse Ged udvider Dyrredskaber Bevægelse {@ Override beskyttet String getSound () {returner "bleat"; } @ Override public String getLocomotion () {returner "gåture"; } @ Override public String spiser () {returner "græs"; } // konstruktør udeladt}

Fra dette tidspunkt bruger vi Java-refleksion til at inspicere aspekter af Java-objekter, der vises i klasserne og grænsefladerne ovenfor.

5.2. Klassenavne

Lad os starte med at hente navnet på et objekt fra Klasse:

@Test offentlig ugyldighed givenObject_whenGetsClassName_thenCorrect () {Object ged = ny ged ("ged"); Class clazz = goat.getClass (); assertEquals ("Ged", clazz.getSimpleName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getCanonicalName ()); }

Bemærk, at getSimpleName metode til Klasse returnerer objektets grundlæggende navn, som det ville fremgå af dets erklæring. Derefter returnerer de to andre metoder det fuldt kvalificerede klassenavn inklusive pakkedeklarationen.

Lad os også se, hvordan vi kan skabe et objekt af Ged klasse, hvis vi kun kender dens fuldt kvalificerede klassenavn:

@ Test offentligt ugyldigt givenClassName_whenCreatesObject_thenCorrect () {Class clazz = Class.forName ("com.baeldung.reflection.Goat"); assertEquals ("Ged", clazz.getSimpleName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getCanonicalName ()); }

Bemærk, at navnet vi overfører til det statiske forName metoden skal indeholde pakkeoplysninger. Ellers får vi en ClassNotFoundException.

5.3. Klassemodifikatorer

Vi kan bestemme de modifikatorer, der bruges i en klasse, ved at kalde getModifiers metode, der returnerer en Heltal. Hver modifikator er en flagbit, som enten er indstillet eller ryddet.

Det java.lang.reflect.Modifier klasse tilbyder statiske metoder, der analyserer den returnerede Heltal for tilstedeværelse eller fravær af et specifikt modifikator.

Lad os bekræfte modifikatorerne for nogle af de klasser, vi definerede ovenfor:

@Test offentlig ugyldighed givenClass_whenRecognisesModifiers_thenCorrect () {Class goatClass = Class.forName ("com.baeldung.reflection.Goat"); Klasse animalClass = Class.forName ("com.baeldung.reflection.Animal"); int goatMods = goatClass.getModifiers (); int animalMods = animalClass.getModifiers (); assertTrue (Modifier.isPublic (goatMods)); assertTrue (Modifier.isAbstract (animalMods)); assertTrue (Modifier.isPublic (animalMods)); }

Vi er i stand til at inspicere modifikatorer af enhver klasse, der er placeret i et bibliotek, som vi importerer til vores projekt.

I de fleste tilfælde skal vi muligvis bruge forName tilgang snarere end fuldblæst instantiering, da det ville være en dyr proces i tilfælde af hukommelsestunge klasser.

5.4. Pakkeoplysninger

Ved hjælp af Java-refleksion er vi også i stand til at få oplysninger om pakken til enhver klasse eller objekt. Disse data er samlet inde i Pakke klasse, der returneres ved et opkald til getPackage metode på klasseobjektet.

Lad os køre en test for at hente pakkenavnet:

@Test offentlig ugyldighed givenClass_whenGetsPackageInfo_thenCorrect () {Ged ged = ny ged ("ged"); Class goatClass = goat.getClass (); Pakke pkg = goatClass.getPackage (); assertEquals ("com.baeldung.reflection", pkg.getName ()); }

5.5. Super klasse

Vi er også i stand til at få superklassen til enhver Java-klasse ved hjælp af Java-refleksion.

I mange tilfælde, især når vi bruger biblioteksklasser eller Java's indbyggede klasser, ved vi muligvis ikke på forhånd superklassen af ​​et objekt, vi bruger, dette underafsnit viser, hvordan man får disse oplysninger.

Så lad os gå videre og bestemme superklassen af Ged. Derudover viser vi det også java.lang.Streng klasse er en underklasse af java.lang.Objekt klasse:

@Test offentlig ugyldighed givenClass_whenGetsSuperClass_thenCorrect () {Ged ged = ny ged ("ged"); String str = "enhver streng"; Class goatClass = goat.getClass (); Class goatSuperClass = goatClass.getSuperclass (); assertEquals ("Animal", goatSuperClass.getSimpleName ()); assertEquals ("Object", str.getClass (). getSuperclass (). getSimpleName ()); }

5.6. Implementerede grænseflader

Ved hjælp af Java-refleksion er vi også i stand til det få listen over grænseflader implementeret af en given klasse.

Lad os hente klassetyperne på de grænseflader, der er implementeret af Ged klasse og Dyr abstrakt klasse:

@Test offentlig ugyldighed givenClass_whenGetsImplementedInterfaces_thenCorrect () {Class goatClass = Class.forName ("com.baeldung.reflection.Goat"); Klasse animalClass = Class.forName ("com.baeldung.reflection.Animal"); Klasse [] goatInterfaces = goatClass.getInterfaces (); Klasse [] animalInterfaces = animalClass.getInterfaces (); assertEquals (1, goatInterfaces.length); assertEquals (1, animalInterfaces.length); assertEquals ("Locomotion", goatInterfaces [0] .getSimpleName ()); assertEquals ("Spise", animalInterfaces [0] .getSimpleName ()); }

Bemærk fra påstandene, at hver klasse kun implementerer en enkelt grænseflade. Ved at inspicere navnene på disse grænseflader finder vi det Ged redskaber Bevægelse og Dyr redskaber Spise, ligesom det vises i vores kode.

Du har måske observeret det Ged er en underklasse af den abstrakte klasse Dyr og implementerer interface-metoden spiser (), derefter, Ged implementerer også Spise interface.

Det er derfor værd at bemærke, at kun de grænseflader, som en klasse udtrykkeligt erklærer som implementeret med redskaber nøgleord vises i det returnerede array.

Så selvom en klasse implementerer grænseflademetoder, fordi dens superklasse implementerer grænsefladen, men underklassen erklærer ikke direkte grænsefladen med redskaber nøgleord, så vil denne grænseflade ikke vises i grænsefladen.

5.7. Konstruktører, metoder og felter

Med Java-refleksion er vi i stand til at inspicere konstruktørerne af ethvert objekts klasse samt metoder og felter.

Vi vil senere kunne se dybere inspektioner på hver af disse komponenter i en klasse, men indtil videre er det tilstrækkeligt bare at få deres navne og sammenligne dem med, hvad vi forventer.

Lad os se, hvordan man får konstruktøren af Ged klasse:

@Test offentligt ugyldigt givenClass_whenGetsConstructor_thenCorrect () {Class goatClass = Class.forName ("com.baeldung.reflection.Goat"); Constructor [] constructors = goatClass.getConstructors (); assertEquals (1, constructors.length); assertEquals ("com.baeldung.reflection.Goat", konstruktører [0] .getName ()); }

Vi kan også inspicere felterne i Dyr klasse som sådan:

@Test offentligt ugyldigt givenClass_whenGetsFields_thenCorrect () {Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); Felt [] felter = animalClass.getDeclaredFields (); Liste actualFields = getFieldNames (felter); assertEquals (2, actualFields.size ()); assertTrue (actualFields.containsAll (Arrays.asList ("navn", "KATEGORI")); }

Ligesom vi kan inspicere metoderne til Dyr klasse:

@Test offentligt ugyldigt givenClass_whenGetsMethods_thenCorrect () {Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); Metode [] metoder = animalClass.getDeclaredMethods (); Liste actualMethods = getMethodNames (metoder); assertEquals (4, actualMethods.size ()); assertTrue (actualMethods.containsAll (Arrays.asList ("getName", "setName", "getSound")); }

Ligesom getFieldNames, vi har tilføjet en hjælpemetode til at hente metodenavne fra en matrix af Metode genstande:

privat statisk liste getMethodNames (Metode [] metoder) {List methodNames = ny ArrayList (); for (Metodemetode: metoder) methodNames.add (method.getName ()); returneringsmetode Navne; }

6. Inspektion af konstruktører

Med Java-refleksion kan vi det inspicere konstruktører af enhver klasse og endda Opret klasseobjekter ved kørsel. Dette er muliggjort af java.lang.reflect.Constructor klasse.

Tidligere kiggede vi kun på, hvordan man får en række Konstruktør objekter, hvorfra vi var i stand til at hente navnene på konstruktørerne.

I dette afsnit vil vi fokusere på, hvordan man henter specifikke konstruktører. I Java, som vi ved, deler ingen konstruktører af en klasse nøjagtig den samme metodesignatur. Så vi vil bruge denne unikhed til at få en konstruktør fra mange.

For at værdsætte funktionerne i denne klasse opretter vi en Fugl underklasse af Dyr med tre konstruktører. Vi implementerer ikke Bevægelse så vi kan specificere denne adfærd ved hjælp af et konstruktørargument for at tilføje endnu mere variation:

offentlig klasse Bird udvider Animal {private boolske gåture; public Bird () {super ("bird"); } offentlig fugl (strengnavn, boolsk vandretur) {super (navn); setWalks (gåture); } offentlig fugl (strengnavn) {super (navn); } offentlige boolske gåture () {returvandringer; } // standard sættere og tilsidesatte metoder}

Lad os bekræfte ved hjælp af refleksion, at denne klasse har tre konstruktører:

@ Test offentlig ugyldighed givenClass_whenGetsAllConstructors_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Constructor [] constructors = birdClass.getConstructors (); assertEquals (3, konstruktører. længde); }

Dernæst henter vi hver konstruktør til Fugl klasse ved at sende konstruktørens parameterklassetyper i deklareret rækkefølge:

@Test offentlig ugyldighed givenClass_whenGetsEachConstructorByParamTypes_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Constructor cons1 = birdClass.getConstructor (); Constructor cons2 = birdClass.getConstructor (String.class); Constructor cons3 = birdClass.getConstructor (String.class, boolean.class); }

Der er ikke behov for påstand, da når en konstruktør med givne parametertyper i den givne rækkefølge ikke findes, får vi en NoSuchMethodException og testen mislykkes automatisk.

I den sidste test vil vi se, hvordan du kan instantiere objekter ved kørsel, mens vi leverer deres parametre:

@ Test offentligt ugyldigt givenClass_whenInstantiatesObjectsAtRuntime_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Constructor cons1 = birdClass.getConstructor (); Constructor cons2 = birdClass.getConstructor (String.class); Constructor cons3 = birdClass.getConstructor (String.class, boolean.class); Bird bird1 = (Bird) cons1.newInstance (); Bird bird2 = (Bird) cons2.newInstance ("Weaver bird"); Bird bird3 = (Bird) cons3.newInstance ("due", sandt); assertEquals ("bird", bird1.getName ()); assertEquals ("Weaver bird", bird2.getName ()); assertEquals ("due", bird3.getName ()); assertFalse (bird1.walks ()); assertTrue (bird3.walks ()); }

Vi instantierer klasseobjekter ved at kalde newInstance metode til Konstruktør klasse og videregive de krævede parametre i deklareret rækkefølge. Vi kaster derefter resultatet til den ønskede type.

Det er også muligt at kalde standardkonstruktøren ved hjælp af Class.newInstance () metode. Denne metode er imidlertid udfaset siden Java 9, og vi bør ikke bruge den til moderne Java-projekter.

Til fugl1, bruger vi standardkonstruktøren, som fra vores Fugl kode, indstiller navnet automatisk til fugl, og vi bekræfter det med en test.

Vi instantierer derefter fugl2 kun med et navn og en test, så husk at når vi ikke indstiller bevægelsesadfærd, da den som standard er falsk, som det ses i de sidste to påstande.

7. Inspektion af felter

Tidligere inspicerede vi kun navnene på felter i dette afsnit, vi viser, hvordan man gør detfå og indstil deres værdier ved kørselstid.

Der er to hovedmetoder, der bruges til at inspicere felter i en klasse ved kørsel: getFields () og getField (fieldName).

Det getFields () metoden returnerer alle tilgængelige offentlige felter i den pågældende klasse. Det returnerer alle de offentlige felter i både klassen og alle superklasser.

For eksempel når vi kalder denne metode på Fugl klasse, får vi kun KATEGORI felt af sin superklasse, Dyr, siden Fugl selv erklærer ikke nogen offentlige felter:

@Test offentlig ugyldighed givenClass_whenGetsPublicFields_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Felt [] felter = birdClass.getFields (); assertEquals (1, fields.length); assertEquals ("KATEGORI", felter [0] .getName ()); }

Denne metode har også en variant kaldet getField som kun returnerer en Mark objekt ved at tage navnet på feltet:

@ Test offentlig ugyldighed givenClass_whenGetsPublicFieldByName_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Feltfelt = birdClass.getField ("KATEGORI"); assertEquals ("KATEGORI", field.getName ()); }

Vi er ikke i stand til at få adgang til private felter, der er deklareret i superklasser og ikke deklareret i børneklassen. Dette er grunden til, at vi ikke har adgang til navn Mark.

Vi kan dog inspicere private felter, der er angivet i den klasse, vi har at gøre med, ved at ringe til getDeclaredFields metode:

@Test offentlig ugyldighed givenClass_whenGetsDeclaredFields_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Felt [] felter = birdClass.getDeclaredFields (); assertEquals (1, fields.length); assertEquals ("går", felter [0] .getName ()); }

Vi kan også bruge dens anden variant, hvis vi kender navnet på feltet:

@Test offentlig ugyldighed givenClass_whenGetsFieldsByName_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Feltfelt = birdClass.getDeclaredField ("går"); assertEquals ("går", field.getName ()); }

Hvis vi får navnet på feltet forkert eller skriver et eksisterende felt, får vi et NoSuchFieldException.

Vi får felttypen som følger:

@ Test offentlig ugyldighed givenClassField_whenGetsType_thenCorrect () {Field field = Class.forName ("com.baeldung.reflection.Bird") .getDeclaredField ("walk"); Class fieldClass = field.getType (); assertEquals ("boolean", fieldClass.getSimpleName ()); }

Dernæst vil vi se på, hvordan du får adgang til feltværdier og ændrer dem. For at være i stand til at få værdien af ​​et felt, endsige indstille det, skal vi først indstille det tilgængeligt ved at ringe setAccessible metode til Mark modstand og pass boolsk rigtigt til det:

@ Test offentlig ugyldighed givenClassField_whenSetsAndGetsValue_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Fuglefugl = (Bird) birdClass.getConstructor (). NewInstance (); Feltfelt = birdClass.getDeclaredField ("går"); field.setAccessible (true); assertFalse (field.getBoolean (fugl)); assertFalse (bird.walks ()); field.set (fugl, sand); assertTrue (field.getBoolean (fugl)); assertTrue (bird.walks ()); }

I ovenstående test konstaterer vi, at værdien af gåture felt er falsk, før det indstilles til sandt.

Bemærk hvordan vi bruger Mark modsætter sig at indstille og hente værdier ved at sende den forekomsten af ​​den klasse, vi har at gøre med, og muligvis den nye værdi, vi vil have feltet i det objekt.

En vigtig ting at bemærke om Mark objekter er, at når det erklæres som offentlig statisk, så har vi ikke brug for en forekomst af klassen, der indeholder dem, vi kan bare bestå nul i stedet og stadig opnå standardværdien af ​​feltet, sådan:

@Test offentlig ugyldighed givenClassField_whenGetsAndSetsWithNull_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Feltfelt = birdClass.getField ("KATEGORI"); field.setAccessible (true); assertEquals ("domestic", field.get (null)); }

8. Inspektionsmetoder

I et tidligere eksempel brugte vi kun refleksion til at inspicere metodenavne. Java-refleksion er dog mere kraftfuld end det.

Med Java-refleksion kan vi det påberåbe sig metoder ved runtime og send dem deres krævede parametre, ligesom vi gjorde for konstruktører. På samme måde kan vi også påberåbe sig overbelastede metoder ved at specificere parametertyper for hver.

Ligesom felter er der to hovedmetoder, som vi bruger til at hente klassemetoder. Det getMethods metoden returnerer en matrix med alle offentlige metoder i klassen og superklasser.

Dette betyder, at vi med denne metode kan få offentlige metoder til java.lang.Objekt klasse som toString, hashCodeog underret alle:

@Test offentlig ugyldighed givenClass_whenGetsAllPublicMethods_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Metode [] metoder = birdClass.getMethods (); Liste methodNames = getMethodNames (metoder); assertTrue (methodNames.containsAll (Arrays .asList ("er lig med", "notifyAll", "hashCode", "går", "spiser", "toString"))); }

For kun at få offentlige metoder til den klasse, vi er interesseret i, skal vi bruge getDeclaredMethods metode:

@ Test offentlig ugyldighed givenClass_whenGetsOnlyDeclaredMethods_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Liste actualMethodNames = getMethodNames (birdClass.getDeclaredMethods ()); Liste expectMethodNames = Arrays .asList ("setWalks", "gange", "getSound", "spiser"); assertEquals (expectMethodNames.size (), actualMethodNames.size ()); assertTrue (expectMethodNames.containsAll (actualMethodNames)); assertTrue (actualMethodNames.containsAll (expectMethodNames)); }

Hver af disse metoder har den entalvariation, der returnerer en enkelt Metode objekt, hvis navn vi kender:

@Test offentligt ugyldigt givenMethodName_whenGetsMethod_thenCorrect () kaster undtagelse {Bird bird = new Bird (); Metode gårMetode = bird.getClass (). GetDeclaredMethod ("går"); Metode setWalksMethod = bird.getClass (). GetDeclaredMethod ("setWalks", boolean.class); assertTrue (walkMethod.canAccess (fugl)); assertTrue (setWalksMethod.canAccess (fugl)); }

Læg mærke til, hvordan vi henter individuelle metoder og specificerer, hvilke parametertyper de tager. Dem, der ikke tager parametertyper, hentes med et tomt variabelargument, hvilket efterlader os med kun et enkelt argument, metodens navn.

Dernæst viser vi, hvordan man påberåber en metode ved kørsel. Vi ved som standard, at gåture attribut for Fugl klasse er falsk, vi vil kalde det setWalks metode og indstil den til rigtigt:

@Test offentlig ugyldighed givenMethod_whenInvokes_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Bird bird = (Bird) birdClass.getConstructor (). NewInstance (); Metode setWalksMethod = birdClass.getDeclaredMethod ("setWalks", boolean.class); Metode walkMethod = birdClass.getDeclaredMethod ("går"); boolske gåture = (boolske) vandrerMetode.opkald (fugl); hævder Falsk (går) assertFalse (bird.walks ()); setWalksMethod.invoke (fugl, sandt); boolsk vandretur2 = (boolsk) gårMetode.opkald (fugl); hævder sandt (går2); assertTrue (bird.walks ()); }

Læg mærke til, hvordan vi først påberåber os gåture metode og kast returtypen til den relevante datatype, og kontroller derefter dens værdi. Derefter påberåber vi os setWalks metode til at ændre denne værdi og teste igen.

9. Konklusion

I denne vejledning har vi dækket Java Reflection API og kigget på, hvordan man bruger det til at inspicere klasser, grænseflader, felter og metoder under kørsel uden forudgående kendskab til deres interne efter kompileringstid.

Den fulde kildekode og eksempler på denne vejledning kan findes på GitHub.