Gids voor Java Reflection

1. Overzicht

In dit artikel zullen we de Java-reflectie onderzoeken, waarmee we runtime-attributen van klassen, interfaces, velden en methoden kunnen inspecteren en / of wijzigen. Dit is vooral handig als we hun namen niet kennen tijdens het compileren.

Bovendien kunnen we nieuwe objecten instantiëren, methoden aanroepen en veldwaarden ophalen of instellen met behulp van reflectie.

2. Projectconfiguratie

Om Java-reflectie te gebruiken, hoeven we geen speciale potten mee te nemen, elke speciale configuratie of Maven-afhankelijkheden. De JDK wordt geleverd met een groep klassen die zijn gebundeld in het java.lang.reflect pakket speciaal voor dit doel.

Dus alles wat we hoeven te doen is de volgende import in onze code te maken:

importeer java.lang.reflect. *;

en we zijn klaar om te gaan.

Om toegang te krijgen tot de klasse, methode en veldinformatie van een instantie noemen we de getClass methode die de weergave van de runtime-klasse van het object retourneert. De teruggekeerden klasse object biedt methoden om toegang te krijgen tot informatie over een klasse.

3. Eenvoudig voorbeeld

Om onze voeten nat te maken, gaan we een heel eenvoudig voorbeeld bekijken dat de velden van een eenvoudig Java-object tijdens runtime inspecteert.

Laten we een eenvoudig maken Persoon klasse met alleen naam en leeftijd velden en helemaal geen methoden. Hier is de Persoonsklasse:

openbare klasse Persoon {privé Stringnaam; privé int leeftijd; }

We zullen nu Java-reflectie gebruiken om de namen van alle velden van deze klasse te ontdekken. Om de kracht van reflectie te waarderen, zullen we een Persoon object en gebruik Object als het referentietype:

@Test openbare leegte gegevenObject_whenGetsFieldNamesAtRuntime_thenCorrect () {Object person = nieuwe persoon (); Veld [] velden = person.getClass (). GetDeclaredFields (); Lijst actualFieldNames = getFieldNames (velden); assertTrue (Arrays.asList ("naam", "leeftijd") .containsAll (actualFieldNames)); }

Deze test laat ons zien dat we in staat zijn om een ​​reeks van F.veld objecten uit onze persoon object, zelfs als de verwijzing naar het object een bovenliggend type van dat object is.

In het bovenstaande voorbeeld waren we alleen geïnteresseerd in de namen van die velden, maar er is veel meer dat kan worden gedaan en we zullen meer voorbeelden hiervan zien in de volgende secties.

Merk op hoe we een helper-methode gebruiken om de werkelijke veldnamen te extraheren, het is een heel eenvoudige code:

privé statische lijst getFieldNames (Veld [] velden) {Lijst fieldNames = nieuwe ArrayList (); voor (Veldveld: velden) fieldNames.add (field.getName ()); return fieldNames; }

4. Gebruiksscenario's voor Java-reflectie

Voordat we verder gaan met de verschillende functies van Java-reflectie, zullen we enkele veelvoorkomende toepassingen bespreken die we ervoor kunnen vinden. Java-reflectie is buitengewoon krachtig en kan op een aantal manieren van pas komen.

In veel gevallen hebben we bijvoorbeeld een naamgevingsconventie voor databasetabellen. We kunnen ervoor kiezen om consistentie toe te voegen door onze tabelnamen vooraf vast te leggen met tbl_, zodat een tabel met leerlinggegevens wordt aangeroepen tbl_student_data.

In dergelijke gevallen noemen we het Java-object dat studentgegevens bevat Leerling of StudentData. Door vervolgens het CRUD-paradigma te gebruiken, hebben we één toegangspunt voor elke bewerking, zodat Creëer operaties ontvangen alleen een Voorwerp parameter.

Vervolgens gebruiken we reflectie om de objectnaam en veldnamen op te halen. Op dit punt kunnen we deze gegevens toewijzen aan een DB-tabel en de objectveldwaarden toewijzen aan de juiste DB-veldnamen.

5. Inspectie van Java-klassen

In deze sectie zullen we de meest fundamentele component in de Java Reflection API onderzoeken. Java-klasseobjecten geven ons, zoals we eerder al zeiden, toegang tot de interne details van elk object.

We gaan interne details onderzoeken, zoals de klassenaam van een object, modificatoren, velden, methoden, geïmplementeerde interfaces, enz.

5.1. Klaar maken

Om een ​​stevige grip te krijgen op de reflectie-API, zoals toegepast op Java-klassen en voorbeelden met variatie te hebben, zullen we een samenvatting maken Dier klasse die de Aan het eten koppel. Deze interface definieert het eetgedrag van elk beton Dier object dat we maken.

Dus ten eerste is hier de Aan het eten koppel:

openbare interface Eten {String eet (); }

en dan het beton Dier implementatie van de Aan het eten koppel:

openbare abstracte klasse Dierlijke implementaties Eten {openbare statische String CATEGORY = "domestic"; private String naam; beschermde abstracte String getSound (); // constructor, standaard getters en setters weggelaten}

Laten we ook een andere interface maken met de naam Voortbeweging die beschrijft hoe een dier beweegt:

openbare interface Locomotion {String getLocomotion (); }

We gaan nu een concrete klasse maken met de naam Geit die zich uitstrekt Dier en werktuigen Voortbeweging. Omdat de superklasse implementeert Aan het eten, Geit zal ook de methoden van die interface moeten implementeren:

openbare klasse Geit breidt uit Dier implementeert Locomotion {@Override beschermde String getSound () {retourneer "bleat"; } @Override public String getLocomotion () {retourneer "wandelingen"; } @Override public String eats () {retourneer "grass"; } // constructor weggelaten}

Vanaf dit punt zullen we Java-reflectie gebruiken om aspecten van Java-objecten te inspecteren die in de bovenstaande klassen en interfaces voorkomen.

5.2. Klassenamen

Laten we beginnen met het ophalen van de naam van een object uit de Klasse:

@Test openbare leegte gegevenObject_whenGetsClassName_thenCorrect () {Object goat = nieuwe geit ("geit"); Klasse clazz = goat.getClass (); assertEquals ("Geit", clazz.getSimpleName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getCanonicalName ()); }

Merk op dat de getSimpleName methode van Klasse geeft de basisnaam van het object terug zoals het zou verschijnen in zijn declaratie. Vervolgens retourneren de andere twee methoden de volledig gekwalificeerde klassenaam inclusief de pakketverklaring.

Laten we ook kijken hoe we een object van de Geit klasse als we alleen de volledig gekwalificeerde klassenaam kennen:

@Test openbare leegte gegevenClassName_whenCreatesObject_thenCorrect () {Class clazz = Class.forName ("com.baeldung.reflection.Goat"); assertEquals ("Geit", clazz.getSimpleName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getName ()); assertEquals ("com.baeldung.reflection.Goat", clazz.getCanonicalName ()); }

Merk op dat de naam die we doorgeven aan de statische forName methode moet de pakketinformatie bevatten. Anders krijgen we een ClassNotFoundException.

5.3. Klasse-modificatoren

We kunnen de modificatoren bepalen die in een klasse worden gebruikt door de getModifiers methode die een Geheel getal. Elke modificator is een vlagbit dat wordt ingesteld of gewist.

De java.lang.reflect.Modifier class biedt statische methoden die het geretourneerde Geheel getal voor de aan- of afwezigheid van een specifieke modificator.

Laten we de modifiers bevestigen van enkele van de klassen die we hierboven hebben gedefinieerd:

@Test openbare leegte gegevenClass_whenRecognisesModifiers_thenCorrect () {Klasse 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)); }

We kunnen modificatoren van elke klasse inspecteren die zich in een bibliotheekpot bevinden die we in ons project importeren.

In de meeste gevallen moeten we de forName benadering in plaats van de volledige instantiatie, aangezien dat een duur proces zou zijn in het geval van geheugenzware klassen.

5.4. Pakket informatie

Door Java-reflectie te gebruiken, kunnen we ook informatie krijgen over het pakket van een klasse of object. Deze gegevens zijn gebundeld in het Pakket klasse die wordt geretourneerd door een aanroep naar getPackage methode op het klasseobject.

Laten we een test uitvoeren om de pakketnaam op te halen:

@Test openbare leegte gegevenClass_whenGetsPackageInfo_thenCorrect () {Geit geit = nieuwe geit ("geit"); Klasse goatClass = goat.getClass (); Pakket pkg = goatClass.getPackage (); assertEquals ("com.baeldung.reflection", pkg.getName ()); }

5.5. Super Klasse

We zijn ook in staat om de superklasse van elke Java-klasse te verkrijgen door Java-reflectie te gebruiken.

In veel gevallen, vooral tijdens het gebruik van bibliotheekklassen of de ingebouwde klassen van Java, weten we misschien niet van tevoren de superklasse van een object dat we gebruiken. Deze subsectie zal laten zien hoe we deze informatie kunnen verkrijgen.

Dus laten we doorgaan en de superklasse van bepalen Geit. Bovendien laten we dat ook zien java.lang.String class is een subklasse van java.lang.Object klasse:

@Test openbare leegte gegevenClass_whenGetsSuperClass_thenCorrect () {Geit goat = nieuwe Geit ("geit"); String str = "elke string"; Klasse goatClass = goat.getClass (); Klasse goatSuperClass = goatClass.getSuperclass (); assertEquals ("Animal", goatSuperClass.getSimpleName ()); assertEquals ("Object", str.getClass (). getSuperclass (). getSimpleName ()); }

5.6. Geïmplementeerde interfaces

Met behulp van Java-reflectie kunnen we dat ook haal de lijst met interfaces op die door een bepaalde klasse zijn geïmplementeerd.

Laten we de klassetypes van de interfaces ophalen die zijn geïmplementeerd door de Geit klasse en de Dier abstracte klasse:

@Test openbare leegte gegevenClass_whenGetsImplementedInterfaces_thenCorrect () {Klasse 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 ("Eten", animalInterfaces [0] .getSimpleName ()); }

Merk op uit de beweringen dat elke klasse slechts één enkele interface implementeert. Als we de namen van deze interfaces inspecteren, vinden we dat Geit werktuigen Voortbeweging en Dier werktuigen Aan het eten, net zoals het in onze code staat.

Dat heb je misschien opgemerkt Geit is een subklasse van de abstracte klasse Dier en implementeert de interfacemethode eet (), dan, Geit implementeert ook de Aan het eten koppel.

Het is daarom vermeldenswaard dat alleen die interfaces waarvan een klasse expliciet verklaart dat ze geïmplementeerd zijn met de werktuigen trefwoord verschijnen in de geretourneerde array.

Dus zelfs als een klasse interfacemethoden implementeert omdat de superklasse die interface implementeert, maar de subklasse die interface niet direct declareert met de werktuigen trefwoord, dan zal die interface niet verschijnen in de reeks interfaces.

5.7. Constructors, methoden en velden

Met Java-reflectie kunnen we de constructors van de klasse van elk object inspecteren, evenals methoden en velden.

We zullen later in staat zijn om diepere inspecties te zien op elk van deze componenten van een klas, maar voorlopig is het voldoende om hun namen te krijgen en ze te vergelijken met wat we verwachten.

Laten we eens kijken hoe we de constructor van het Geit klasse:

@Test openbare leegte gegevenClass_whenGetsConstructor_thenCorrect () {Klasse goatClass = Class.forName ("com.baeldung.reflection.Goat"); Constructor [] constructors = goatClass.getConstructors (); assertEquals (1, constructors.length); assertEquals ("com.baeldung.reflection.Goat", constructors [0] .getName ()); }

We kunnen ook de velden van de Dier klasse zo:

@Test openbare ongeldige gegevenClass_whenGetsFields_thenCorrect () {Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); Veld [] velden = animalClass.getDeclaredFields (); Lijst actualFields = getFieldNames (velden); assertEquals (2, actualFields.size ()); assertTrue (actualFields.containsAll (Arrays.asList ("naam", "CATEGORY"))); }

Net zoals we de methoden van de Dier klasse:

@Test openbare leegte gegevenClass_whenGetsMethods_thenCorrect () {Class animalClass = Class.forName ("com.baeldung.reflection.Animal"); Methode [] methodes = animalClass.getDeclaredMethods (); Lijst actualMethods = getMethodNames (methoden); assertEquals (4, actualMethods.size ()); assertTrue (actualMethods.containsAll (Arrays.asList ("getName", "setName", "getSound"))); }

Net als getFieldNames, hebben we een hulpmethode toegevoegd om de namen van methoden op te halen uit een reeks Methode voorwerpen:

privé statische lijst getMethodNames (methode [] methoden) {List methodNames = nieuwe ArrayList (); voor (Methode methode: methodes) methodNames.add (method.getName ()); return methodNames; }

6. Inspecteren van constructeurs

Met Java-reflectie kunnen we dat inspecteren constructeurs van elke klasse en zelfs maak klasseobjecten tijdens runtime. Dit wordt mogelijk gemaakt door de java.lang.reflect.Constructor klasse.

Eerder hebben we alleen gekeken hoe we de reeks Constructor objecten, waaruit we de namen van de constructeurs konden halen.

In deze sectie zullen we ons concentreren op het ophalen van specifieke constructors. In Java, zoals we weten, delen geen twee constructeurs van een klasse exact dezelfde methode-handtekening. Dus we zullen deze uniciteit gebruiken om uit vele een constructor te krijgen.

Om de kenmerken van deze klasse te waarderen, zullen we een Vogel subklasse van Dier met drie constructeurs. We zullen niet implementeren Voortbeweging zodat we dat gedrag kunnen specificeren met behulp van een constructorargument, om nog meer variatie toe te voegen:

openbare klasse Bird breidt Animal {privé booleaanse wandelingen uit; openbare Bird () {super ("bird"); } public Bird (String naam, booleaanse wandelingen) {super (naam); setWalks (wandelingen); } public Bird (String name) {super (name); } openbare booleaanse wandelingen () {retourwandelingen; } // standaard setters en overschreven methoden}

Laten we door middel van reflectie bevestigen dat deze klasse drie constructors heeft:

@Test openbare leegte gegevenClass_whenGetsAllConstructors_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Constructor [] constructors = birdClass.getConstructors (); assertEquals (3, constructors.length); }

Vervolgens halen we elke constructor op voor de Vogel klasse door de parameterklassen van de constructor door te geven in de aangegeven volgorde:

@Test openbare leegte gegevenClass_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); }

Er is geen noodzaak voor bewering, want als een constructor met gegeven parametertypen in de gegeven volgorde niet bestaat, krijgen we een NoSuchMethodException en de test zal automatisch mislukken.

In de laatste test zullen we zien hoe we objecten tijdens runtime kunnen instantiëren terwijl we hun parameters opgeven:

@Test openbare leegte gegevenClass_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 ("dove", true); assertEquals ("bird", bird1.getName ()); assertEquals ("Weaver bird", bird2.getName ()); assertEquals ("dove", bird3.getName ()); assertFalse (bird1.walks ()); assertTrue (bird3.walks ()); }

We instantiëren klasseobjecten door de newInstance methode van Constructor class en het doorgeven van de vereiste parameters in de aangegeven volgorde. Vervolgens casten we het resultaat naar het gewenste type.

Het is ook mogelijk om de standaardconstructor aan te roepen met de Class.newInstance () methode. Deze methode is echter verouderd sinds Java 9 en we zouden deze niet moeten gebruiken in moderne Java-projecten.

Voor vogel1, gebruiken we de standaard constructor die van onze Vogel code, zet automatisch de naam op bird en dat bevestigen we met een test.

We instantiëren dan vogel2 met alleen een naam en ook een test, onthoud dat wanneer we voortbewegingsgedrag niet instellen als standaard op false, zoals te zien is in de laatste twee beweringen.

7. Velden inspecteren

Voorheen inspecteerden we alleen de namen van velden, in deze sectie, we zullen laten zien hoeget en stel hun waarden in tijdens runtime.

Er zijn twee hoofdmethoden die worden gebruikt om velden van een klasse tijdens runtime te inspecteren: getFields () en getField (veldnaam).

De getFields () methode retourneert alle toegankelijke openbare velden van de betreffende klasse. Het retourneert alle openbare velden in zowel de klasse als alle superklassen.

Als we deze methode bijvoorbeeld aanroepen op de Vogel klasse, krijgen we alleen de CATEGORIE gebied van zijn superklasse, Dier, sinds Vogel zelf declareert geen openbare velden:

@Test openbare ongeldig gegevenClass_whenGetsPublicFields_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Veld [] velden = birdClass.getFields (); assertEquals (1, fields.length); assertEquals ("CATEGORY", velden [0] .getName ()); }

Deze methode heeft ook een variant genaamd getField die er slechts één retourneert Veld object door de naam van het veld te nemen:

@Test openbare leegte gegevenClass_whenGetsPublicFieldByName_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Veldveld = birdClass.getField ("CATEGORY"); assertEquals ("CATEGORY", field.getName ()); }

We hebben geen toegang tot privévelden die zijn gedeclareerd in superklassen en niet zijn gedeclareerd in de onderliggende klasse. Dit is de reden waarom we geen toegang hebben tot het naam veld.

We kunnen echter privévelden inspecteren die zijn gedeclareerd in de klasse waarmee we te maken hebben door de getDeclaredFields methode:

@Test openbare leegte gegevenClass_whenGetsDeclaredFields_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Veld [] velden = birdClass.getDeclaredFields (); assertEquals (1, fields.length); assertEquals ("wandelingen", velden [0] .getName ()); }

We kunnen ook de andere variant gebruiken als we de naam van het veld kennen:

@Test openbare leegte gegevenClass_whenGetsFieldsByName_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Veldveld = birdClass.getDeclaredField ("wandelingen"); assertEquals ("wandelingen", field.getName ()); }

Als we de naam van het veld verkeerd krijgen of een niet-bestaand veld typen, krijgen we een NoSuchFieldException.

We krijgen het veldtype als volgt:

@Test openbare leegte gegevenClassField_whenGetsType_thenCorrect () {Veldveld = Class.forName ("com.baeldung.reflection.Bird") .getDeclaredField ("wandelingen"); Klasse fieldClass = field.getType (); assertEquals ("boolean", fieldClass.getSimpleName ()); }

Vervolgens gaan we bekijken hoe u toegang krijgt tot veldwaarden en hoe u deze kunt wijzigen. Om de waarde van een veld te kunnen krijgen, laat staan ​​om het in te stellen, moeten we eerst instellen dat het toegankelijk is door te bellen setAccessible methode op de Veld object en geef boolean door waar naar het:

@Test openbare leegte gegevenClassField_whenSetsAndGetsValue_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Bird bird = (Bird) birdClass.getConstructor (). NewInstance (); Veldveld = birdClass.getDeclaredField ("wandelingen"); field.setAccessible (true); assertFalse (field.getBoolean (vogel)); assertFalse (bird.walks ()); field.set (vogel, waar); assertTrue (field.getBoolean (vogel)); assertTrue (bird.walks ()); }

In de bovenstaande test stellen we vast dat inderdaad de waarde van de wandelingen veld is false voordat het op true wordt ingesteld.

Merk op hoe we de Veld object om waarden in te stellen en op te halen door het de instantie van de klasse waarmee we te maken hebben door te geven en mogelijk de nieuwe waarde die we willen dat het veld in dat object heeft.

Een belangrijk ding om op te merken Veld objecten is dat wanneer het wordt verklaard als openbare statische, dan hebben we geen instantie nodig van de klasse die ze bevat, we kunnen gewoon doorgeven nul op zijn plaats en toch de standaardwaarde van het veld verkrijgen, zoals zo:

@Test openbare ongeldig gegevenClassField_whenGetsAndSetsWithNull_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Veldveld = birdClass.getField ("CATEGORY"); field.setAccessible (true); assertEquals ("binnenlands", field.get (null)); }

8. Inspectiemethoden

In een vorig voorbeeld hebben we reflectie alleen gebruikt om de namen van methoden te inspecteren. De Java-reflectie is echter krachtiger dan dat.

Met Java-reflectie kunnen we dat roep methoden aan op looptijd en geef ze hun vereiste parameters door, net zoals we deden voor constructeurs. Evenzo kunnen we ook overbelaste methoden aanroepen door van elk parametertypen te specificeren.

Net als velden zijn er twee hoofdmethoden die we gebruiken voor het ophalen van klassemethoden. De getMethods method retourneert een array van alle openbare methoden van de klasse en superklassen.

Dit betekent dat we met deze methode openbare methoden van de java.lang.Object klasse zoals toString, hashCode, en informerenAll:

@Test openbare leegte gegevenClass_whenGetsAllPublicMethods_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Methode [] methodes = birdClass.getMethods (); List methodNames = getMethodNames (methoden); assertTrue (methodNames.containsAll (Arrays .asList ("equals", "informerenAll", "hashCode", "wandelingen", "eats", "toString"))); }

Om alleen openbare methoden te krijgen van de klasse waarin we geïnteresseerd zijn, moeten we getDeclaredMethods methode:

@Test openbare leegte gegevenClass_whenGetsOnlyDeclaredMethods_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Lijst actualMethodNames = getMethodNames (birdClass.getDeclaredMethods ()); Lijst verwachteMethodNames = Arrays .asList ("setWalks", "wandelingen", "getSound", "eet"); assertEquals (verwachteMethodNames.size (), actualMethodNames.size ()); assertTrue (verwachteMethodNames.containsAll (actualMethodNames)); assertTrue (actualMethodNames.containsAll (verwachteMethodNames)); }

Elk van deze methoden heeft de singuliere variatie die een enkele retourneert Methode object waarvan we de naam kennen:

@Test openbare leegte gegevenMethodName_whenGetsMethod_thenCorrect () gooit uitzondering {Bird bird = new Bird (); Methode wandelingenMethod = bird.getClass (). GetDeclaredMethod ("wandelingen"); Methode setWalksMethod = bird.getClass (). GetDeclaredMethod ("setWalks", boolean.class); assertTrue (walkingMethod.canAccess (bird)); assertTrue (setWalksMethod.canAccess (bird)); }

Merk op hoe we individuele methoden ophalen en specificeren welke parametertypes ze gebruiken. Degenen die geen parametertypen aannemen, worden opgehaald met een leeg variabel argument, waardoor er slechts één argument overblijft, de naam van de methode.

Vervolgens laten we zien hoe u een methode tijdens runtime aanroept. We weten standaard dat de wandelingen attribuut van de Vogel klasse is false, we willen haar noemen setWalks methode en stel deze in op waar:

@Test openbare leegte gegevenMethod_whenInvokes_thenCorrect () {Class birdClass = Class.forName ("com.baeldung.reflection.Bird"); Bird bird = (Bird) birdClass.getConstructor (). NewInstance (); Methode setWalksMethod = birdClass.getDeclaredMethod ("setWalks", boolean.class); Methode wandelingenMethod = birdClass.getDeclaredMethod ("wandelingen"); boolean wandelingen = (boolean) wandelingenMethod.invoke (vogel); assertFalse (loopt); assertFalse (bird.walks ()); setWalksMethod.invoke (bird, true); boolean wandelingen2 = (boolean) wandelingenMethod.invoke (vogel); assertTrue (wandelingen2); assertTrue (bird.walks ()); }

Merk op hoe we eerst het wandelingen methode en cast het retourtype naar het juiste gegevenstype en controleer vervolgens de waarde ervan. We doen dan later een beroep op de setWalks methode om die waarde te veranderen en opnieuw te testen.

9. Conclusie

In deze tutorial hebben we de Java Reflection API behandeld en gekeken hoe je deze kunt gebruiken om klassen, interfaces, velden en methoden tijdens runtime te inspecteren zonder voorafgaande kennis van hun interne onderdelen door compilatietijd.

De volledige broncode en voorbeelden voor deze tutorial zijn te vinden op GitHub.