{"id":405,"date":"2011-11-03T14:47:19","date_gmt":"2011-11-03T12:47:19","guid":{"rendered":"http:\/\/www.kristiansborg.dk\/bibliotek\/?page_id=405"},"modified":"2011-11-03T14:49:04","modified_gmt":"2011-11-03T12:49:04","slug":"kapitel-7-reflections","status":"publish","type":"page","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/","title":{"rendered":"Kapitel 7 Reflections"},"content":{"rendered":"<p>Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.<\/p>\n<div style=\"border: 1px solid red; color: red\">\n<b>Du l\u00e6ser en gammel bog<\/b><br \/>\nDen bog, du l\u00e6ser her, er fra 1998, og mange ting kan have \u00e6ndret sig siden da.<br \/>\nVi h\u00e5ber, at du stadig kan finde relevant information i den.<br \/>\nHvis du vil l\u00e6se aktuelle oplysninger om de avancerede dele af Java, anbefaler vi<br \/>\nbogen <a href=\"http:\/\/clk.tradedoubler.com\/click?p(197229)a(2029446)g(19172914)url(http:\/\/www.adlibris.com\/dk\/product.aspx?isbn=0132354799)\"  target=\"_blank\">Core Java &#8211; Advanced Features<\/a><img decoding=\"async\" src=\"http:\/\/impdk.tradedoubler.com\/imp?type(inv)g(19172914)a(2029446)\" \/>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Fordelene ved denne fremgangsm\u00e5de er mange. F\u00f8rst og fremmest bliver man fri for en enorm m\u00e6ngde if-s\u00e6tninger, der skal kontrollere, hvad brugeren har indtastet, og derefter kalde den p\u00e5g\u00e6ldende funktion. Derudover bliver systemet nemmere at vedligeholde. N\u00e5r man implementerer en ny funktion, er den omg\u00e5ende tilg\u00e6ngelig for brugeren \u2013 man beh\u00f8ver ikke f\u00f8rst tilf\u00f8je den til listen over gyldige kommandoer.<\/p>\n<p>&nbsp;<\/p>\n<p>Der er imidlertid ogs\u00e5 en r\u00e6kke problemer, der skal overvindes. For eksempel tager mange metoder en eller flere parametre. Det skal s\u00e5ledes v\u00e6re muligt for brugeren at indtaste navnet p\u00e5 metoden samt de parametre, der skal bruges, hvorefter metoden bliver kaldt med de parametre.<\/p>\n<p>&nbsp;<\/p>\n<p>Reflections kan langt fra anvendes i ethvert projekt, men der er en del opgaver, der med fordel kan l\u00f8ses ved brug af reflections. Det g\u00e6lder for eksempel netv\u00e6rkskommunikation, hvor reflections kan v\u00e6re et godt alternativ eller supplement til remote method invocation (RMI). Ogs\u00e5 ved implementering af scriptsprog har reflections en fordel.<\/p>\n<p>&nbsp;<\/p>\n<h1>Dynamisk metodekald<\/h1>\n<p>&nbsp;<\/p>\n<p>Dynamisk metodekald er n\u00f8glen til det hele, og derfor vil det blive gennemg\u00e5et f\u00f8rst. Da Java er objektorienteret kan metoderne ikke st\u00e5 alene \u2013 de skal v\u00e6re tilknyttet en klasse. Man kan finde et objekts klasse ved at benytte funktionen objekt.getClass(). Denne funktion returnerer et objekt af typen java.lang.Class:<\/p>\n<p>&nbsp;<\/p>\n<p>public final class Class extends Object<\/p>\n<p>{<\/p>\n<p>public static Class forName(String className) throws ClassNotFoundException;<\/p>\n<p>public Object newInstance() throws InstantiationException, IllegalAccessException;<\/p>\n<p>public boolean isInstance(Object obj);<\/p>\n<p>public boolean isPrimitive();<\/p>\n<p>&nbsp;<\/p>\n<p>public String getName();<\/p>\n<p>public int getModifiers();<\/p>\n<p>public ClassLoader getClassLoader();<\/p>\n<p>public Class getSuperclass();<\/p>\n<p>public Class[] getInterfaces();<\/p>\n<p>public Field[] getFields()<\/p>\n<p>throws SecurityException;<\/p>\n<p>&nbsp;<\/p>\n<p>public Method[] getMethods() throws SecurityException;<\/p>\n<p>public Constructor[] getConstructors();<\/p>\n<p>public Method getMethod(String name, Class[] parameterTypes)<\/p>\n<p>throws NoSuchMethodException, SecurityException;<\/p>\n<p>public Constructor getConstructor(Class[] parameterTypes)<\/p>\n<p>throws NoSuchMethodException, SecurityException;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r man har fundet ud af, hvilken klasse, der er tale om, kan man bruge getMethod til at finde den metode, der skal kaldes. Det er imidlertid ikke s\u00e5 let, som det lyder. Java underst\u00f8tter overloading, hvilket betyder at flere forskellige funktioner i samme klasse godt kan have det samme navn. Man kender i s\u00e5 fald forskel p\u00e5 dem p\u00e5 deres forskellige signatur \u2013 det vil sige returtype og antallet og\/eller typen af parametre. getMethod tager derfor to parametre:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>en String, der angiver metodens navn<\/li>\n<li>et array af Class-objekter, der angiver typen af parametrene i den r\u00e6kkef\u00f8lge de forekommer i metodens signatur.<\/li>\n<\/ul>\n<p>Indeholder klassen ikke en public metode, der svarer til den angivne signatur, opst\u00e5r en NoSuchMethodException. Hvis metoden bliver fundet, bliver der returneret en reference til den i form af et java.lang.reflect.Method-objekt:<\/p>\n<p>&nbsp;<\/p>\n<p>public final class Method extends Object implements Member<\/p>\n<p>{<\/p>\n<p>public String getName();<\/p>\n<p>public int getModifiers();<\/p>\n<p>public Class getReturnType();<\/p>\n<p>public Class[] getParameterTypes();<\/p>\n<p>public Class[] getExceptionTypes();<\/p>\n<p>public Object invoke(Object obj, Object[] args)<\/p>\n<p>throws NullPointerException, IllegalArgumentException,<\/p>\n<p>IllegalAccessException, InvocationTargetException;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Det Method-objekt, der returneres fra getMethod, kan man kalde metoden invoke p\u00e5 \u2013 s\u00e5 bliver metoden udf\u00f8rt. invoke tager to parametre:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>Det objekt, metoden skal kaldes p\u00e5. Det er dette objekt, metoden getClass blev kaldt p\u00e5.<\/li>\n<li>Et array af objekter, svarende til de aktuelle parametre i metodekaldet.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Ved brug af invoke-metoden skal f\u00f8lgende bem\u00e6rkes:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>Primitive typer kan ikke overf\u00f8res i et array af objekter, da de ikke er objekter. I stedet skal wrapper-klasserne bruges (Integer i stedet for int, Float i stedet for float, osv.). Konverteringen fra wrapper-typerne i kaldet til invoke til de primitive typer i det reelle funktionskald foretages automatisk.Hvis det argument, der fors\u00f8ges konverteret til en primitiv type, er null opst\u00e5r en NullPointerException.\n<p>Hvis det argument, der fors\u00f8ges konverteret til en primitiv type, ikke er en af Javas standard wrapper-klasser, opst\u00e5r en IllegalArgumentException.<\/li>\n<li>Hvis metoden returnerer en primitiv type, bliver returv\u00e6rdien automatisk konverteret til en wrapper-type. Det er herefter op til programm\u00f8ren at konvertere den tilbage til en primitiv type, hvis n\u00f8dvendigt.<\/li>\n<li>Hvis den metode, der bliver kaldt er en klassemetode \u2013 det vil sige, at den er erkl\u00e6ret static \u2013 bruges den f\u00f8rste parameter i kaldet til invoke ikke, og den kan v\u00e6re null.<\/li>\n<li>Hvis metoden ikke er en klassemetode, og objektet angives som null opst\u00e5r en NullPointerException.<\/li>\n<li>Hvis objektet, der sendes med som parameter til invoke, ikke definerer den p\u00e5g\u00e6ldende metode, opst\u00e5r en IllegalArgumentException.<\/li>\n<li>Hvis metodekaldet medf\u00f8rer adgangskontrol, og metoden ikke er tilg\u00e6ngelig, opst\u00e5r en IllegalAccessException.<\/li>\n<li>Hvis typerne af de aktuelle parametre angivet i kaldet til invoke ikke passer til de formelle parametre angivet i den p\u00e5g\u00e6ldende metodes signatur, opst\u00e5r en IllegalArgumentException.<\/li>\n<li>Hvis metoden ikke tager nogen parametre, ses bort fra arrayet af parametre i kaldet til invoke. Parametrene kan i s\u00e5 fald angives som null<\/li>\n<li>Hvis udf\u00f8rslen af metoden resulterer i en exception, bliver denne exception grebet af invoke-metoden. Herefter bliver den placeret i en InvokationTargetException, som invoke genererer og sender videre.<\/li>\n<li>Hvis metoden udf\u00f8res succesfuldt, returneres metodens returv\u00e6rdi af invoke \u2013 eventuelt konverteret til en wrapper-klasse. Hvis metoden returnerer void, returnerer invoke null.<\/li>\n<\/ul>\n<p>Alt i alt skal der alts\u00e5 foretages to skridt for at udf\u00f8re et dynamisk kald af en metode:<\/p>\n<p>&nbsp;<\/p>\n<ol>\n<li>Der skal findes en reference til den p\u00e5g\u00e6ldende metode.<\/li>\n<li>Metoden skal kaldes.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Det lyder umiddelbart meget simpelt, men det er slet ikke s\u00e5 let at programmere. Det er for besv\u00e6rligt at skulle til at oprette et array af Class-objekter, hver gang man skal have en reference til en metode. Derefter skal man oprette et array af objekter, der indeholder de aktuelle parametre i metodekaldet. Det<\/p>\n<p>&nbsp;<\/p>\n<p>ville v\u00e6re v\u00e6sentligt nemmere, hvis man kunne opbevare argumenterne i en klasse, der b\u00e5de h\u00e5ndterede de aktuelle argumenter, men ogs\u00e5 deres klasser. Til at l\u00f8se denne opgave kan en klasse ArgumentList oprettes. Et eksempel p\u00e5 en s\u00e5dan klasses ses herunder:<\/p>\n<p>&nbsp;<\/p>\n<p>import java.util.Vector;<\/p>\n<p>&nbsp;<\/p>\n<p>public class ArgumentList<\/p>\n<p>{<\/p>\n<p>\/\/ Variabler til at h\u00e5ndtere henholdsvis klasser og objekter<\/p>\n<p>protected Vector classes;<\/p>\n<p>protected Vector objects;<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Constructor<\/p>\n<p>public ArgumentList ()<\/p>\n<p>{<\/p>\n<p>classes = new Vector();<\/p>\n<p>objects = new Vector();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Funktioner til at tilf\u00f8je argumenter<\/p>\n<p>\/\/ Primitive typer konverteres til wrapper-klasser<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (boolean b)<\/p>\n<p>{<\/p>\n<p>addArg (new Boolean (b));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (byte b)<\/p>\n<p>{<\/p>\n<p>addArg (new Byte (b));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (char c)<\/p>\n<p>{<\/p>\n<p>addArg (new Character (c));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (int i)<\/p>\n<p>{<\/p>\n<p>addArg (new Integer (i));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (short s)<\/p>\n<p>{<\/p>\n<p>addArg (new Short (s));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (long l)<\/p>\n<p>{<\/p>\n<p>addArg (new Long (l));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (float f)<\/p>\n<p>{<\/p>\n<p>addArg (new Float (f));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (double d)<\/p>\n<p>{<\/p>\n<p>addArg (new Double (d));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Inds\u00e6t et objekt &#8211; ingen konvertering n\u00f8dvendig<\/p>\n<p>&nbsp;<\/p>\n<p>public void addArg (Object o)<\/p>\n<p>{<\/p>\n<p>objects.addElement (o);<\/p>\n<p>classes.addElement (o.getClass());<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Funktioner til returnering af argumenter<\/p>\n<p>&nbsp;<\/p>\n<p>public Class[] getClasses ()<\/p>\n<p>{<\/p>\n<p>classes.trimToSize();<\/p>\n<p>int classCount = classes.size();<\/p>\n<p>&nbsp;<\/p>\n<p>Class[] cl = new Class [classCount];<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; classCount; i++)<\/p>\n<p>cl[i] = (Class) classes.elementAt (i);<\/p>\n<p>&nbsp;<\/p>\n<p>return cl;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public Object[] getArguments ()<\/p>\n<p>{<\/p>\n<p>objects.trimToSize();<\/p>\n<p>int argumentCount = objects.size();<\/p>\n<p>&nbsp;<\/p>\n<p>Object[] obj = new Object [argumentCount];<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; argumentCount; i++)<\/p>\n<p>obj[i] = objects.elementAt (i);<\/p>\n<p>&nbsp;<\/p>\n<p>return obj;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Klassen gemmer de klasser og objekter, der siden skal bruges som argumenter, i en instans af den dynamiske klasse java.util.Vector. Til at tilf\u00f8je argumenter til listen bruges en r\u00e6kke overloadede metoder, der alle hedder addArg. Der findes en version af addArg til hver af de primitive typer. Disse metoder opretter et objekt af den p\u00e5g\u00e6ldende primitive types wrapper-klasse og kalder videre til den udgave af addArg, der tager et objekt som parameter.<\/p>\n<p>&nbsp;<\/p>\n<p>Denne udgave af metoden er den eneste, der foretager et virkeligt stykke arbejde. Den tilf\u00f8jer objektet til listen over objekter, og tilf\u00f8jer objektets klasse til listen over klasser. Som klassen er skitseret her, skal argumenterne tilf\u00f8jes i samme r\u00e6kkef\u00f8lge som de forekommer i metodens signatur. En forbedring af klassen kan indeholde funktioner, der kan tilf\u00f8je argumenter p\u00e5 en bestemt position.<\/p>\n<p>&nbsp;<\/p>\n<p>Der findes to funktioner, der returnerer information om argumenterne. Det er getClasses og getArguments. getClasses returnerer et array af Class-objekter. Det sker ved at genneml\u00f8be vektoren og konvertere hvert element til Class. getArguments foretager det samme for objects-vektoren \u2013 blot bliver elementerne her ikke konverteret, da de allerede er af typen Object.<\/p>\n<p>&nbsp;<\/p>\n<p>Med ArgumentList p\u00e5 plads er det muligt at lave en generel funktion, der foretager et dynamisk metodekald:<\/p>\n<p>&nbsp;<\/p>\n<p>import java.lang.reflect.Method;<\/p>\n<p>import java.lang.Class;<\/p>\n<p>&nbsp;<\/p>\n<p>public class Invoker<\/p>\n<p>{<\/p>\n<p>public static Object dynamicInvocation (Object obj, String methodName,<\/p>\n<p>ArgumentList args) throws Exception<\/p>\n<p>{<\/p>\n<p>Method method = obj.getClass().getMethod (methodName, args.getClasses());<\/p>\n<p>return method.invoke (obj, args.getArguments());<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Invoker-klassen indeholder kun en enkelt funktion. Det er den statiske dynamicInvocation, der tager tre parametre:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>En reference til det objekt, metoden skal kaldes p\u00e5.<\/li>\n<li>Navnet p\u00e5 den metode, der skal kaldes.<\/li>\n<li>De parametre, der skal overf\u00f8res til funktionen, samlet i en ArgumentList.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h1>Dynamisk instantiering af klasser<\/h1>\n<p>&nbsp;<\/p>\n<p>I de ovenn\u00e6vnte eksempler er klasserne blevet instantieret p\u00e5 den s\u00e6dvanlige m\u00e5de. Herefter er getClass-metoden blevet kaldt p\u00e5 objektet, for at f\u00e5 en reference til et Class\u00ad-objekt. Det er imidlertid ogs\u00e5 muligt at instantiere klasser dynamisk. Det g\u00f8res ved hj\u00e6lp af den statiske funktion<\/p>\n<p>&nbsp;<\/p>\n<p>public static Class forName(String className) throws ClassNotFoundException;<\/p>\n<p>&nbsp;<\/p>\n<p>Denne funktion findes i klassen Class.<\/p>\n<p>&nbsp;<\/p>\n<p>Metoden tager navnet p\u00e5 klassen, der skal oprettes en instans af, som parameter. Kan klassen ikke findes, opst\u00e5r en ClassNotFoundException.<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r man har referencen til klassen, er man klar til at instantiere et objekt af den. Det g\u00f8r man ved hj\u00e6lp af metoden<\/p>\n<p>&nbsp;<\/p>\n<p>public Object newInstance() throws InstantiationException,<\/p>\n<p>IllegalAccessException;<\/p>\n<p>&nbsp;<\/p>\n<p>Metoden returnerer et objekt, og returv\u00e6rdien skal derfor castes til den rette klasse. Nedenst\u00e5ende er et eksempel p\u00e5 brug af dynamisk instantiering:<\/p>\n<p>&nbsp;<\/p>\n<p>import java.awt.Frame;<\/p>\n<p>import java.awt.Label;<\/p>\n<p>&nbsp;<\/p>\n<p>public class DynamicLabel extends Frame<\/p>\n<p>{<\/p>\n<p>public DynamicLabel ()<\/p>\n<p>{<\/p>\n<p>super (&#8220;DynamicLabel&#8221;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>&nbsp;<\/p>\n<p>Class labelClass = null;<\/p>\n<p>Label label = null;<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>labelClass = Class.forName (&#8220;java.awt.Label&#8221;);<\/p>\n<p>}<\/p>\n<p>catch (ClassNotFoundException cnfe)<\/p>\n<p>{<\/p>\n<p>System.err.println (cnfe.toString());<\/p>\n<p>System.exit (1);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>label = (Label) labelClass.newInstance();<\/p>\n<p>}<\/p>\n<p>catch (IllegalAccessException iae)<\/p>\n<p>{<\/p>\n<p>System.err.println (iae.toString());<\/p>\n<p>System.exit (2);<\/p>\n<p>}<\/p>\n<p>catch (InstantiationException ie)<\/p>\n<p>{<\/p>\n<p>System.err.println (ie.toString());<\/p>\n<p>System.exit (3);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>ArgumentList argList = new ArgumentList();<\/p>\n<p>argList.addArg (&#8220;Dette er min label&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>&nbsp;<\/p>\n<p>Invoker.dynamicInvocation (label, &#8220;setText&#8221;, argList);<\/p>\n<p>}<\/p>\n<p>catch (Exception e)<\/p>\n<p>{<\/p>\n<p>System.err.println (e.toString());<\/p>\n<p>System.exit (4);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>DynamicLabel me = new DynamicLabel();<\/p>\n<p>&nbsp;<\/p>\n<p>me.add (&#8220;Center&#8221;, label);<\/p>\n<p>&nbsp;<\/p>\n<p>me.setVisible(true);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses, skal man angive det komplette klassenavn for at f\u00e5 en reference til klassen. Det er med andre ord ikke nok at angive Label \u2013 man skal angive hele navnet java.awt.Label.<\/p>\n<p>&nbsp;<\/p>\n<p>Eksemplet viser ogs\u00e5, hvilke exceptions man skal v\u00e6re opm\u00e6rksom p\u00e5. Class.forName kan ende i en ClassNotFoundException, hvis klassen ikke kan findes. Instantieringen af klassen ved hj\u00e6lp af newInstance kan ogs\u00e5 medf\u00f8re exceptions. IllegalAccessException hvis man ikke har rettigheder til at instantiere klassen, og InstantiationException hvis man fors\u00f8ger at instantiere en abstrakt klasse eller et interface, eller hvis man kalder funktionen p\u00e5 et objekt, der repr\u00e6senterer en primitiv type eller Void.<\/p>\n<p>&nbsp;<\/p>\n<p>Efter instantieringen af objektet, bliver der gjort klar til at kalde metoden setText (String). Det g\u00f8res ved at oprette et ArgumentList-objekt, hvor teksten \u201dDette er min label\u201d tilf\u00f8jes til listen over parametre. Dern\u00e6st bruges Invoker-klassens dynamicInvocation-metode, som beskrevet tidligere i kapitlet. Den metode kan resultere i en generel Exception, hvis kaldet til den underliggende metode mislykkes eller medf\u00f8rer en exception.<\/p>\n<p>&nbsp;<\/p>\n<p>Resten af eksemplet s\u00f8rger blot for at f\u00e5 labelen tilf\u00f8jet til vinduet og f\u00e5 vinduet vist.<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses, giver reflections v\u00e6sentligt mere kode end almindelig, statisk programmering.<\/p>\n<p>&nbsp;<\/p>\n<h1>Indl\u00e6sning af klasser<\/h1>\n<p>&nbsp;<\/p>\n<p>Forrige afsnit forklarede, hvordan man kunne instantiere klasser dynamisk, men det sprang let og elegant over, hvordan klasserne blev indl\u00e6st. Til dette bruges en <em>class loader<\/em>. Normalt bliver klasser indl\u00e6st fra den lokale computer. I Windows og Unix bliver klasser indl\u00e6st fra de biblioteker, der er angivet i CLASSPATH-variablen. S\u00e5dan beh\u00f8ver det imidlertid ikke at v\u00e6re. Der er ikke noget, der hindrer, at man skriver sin egen class loader, der g\u00f8r det muligt at indl\u00e6se klasser fra andre computere via et netv\u00e6rk. F\u00f8rst vil det nok v\u00e6re en god id\u00e9 at se p\u00e5, hvordan den almindelige class loader virker og bruges.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>public abstract class ClassLoader extends Object<\/p>\n<p>{<\/p>\n<p>protected final java.lang.Class defineClass(java.lang.String, byte[] , int off, int len) throws java.lang.ClassFormatException.<\/p>\n<p>public static java.lang.ClassLoader getBaseClassLoader ();<\/p>\n<p>public java.lang.Class loadClass (java.lang.String) throws java.lang.ClassNotFoundException;<\/p>\n<p>protected final void resolveClass(<a href=\"java.lang.Class.html\">java.lang.Class<\/a>)<\/p>\n<p>&nbsp;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Klassen ClassLoader er en abstrakt klasse, som andre klasser kan nedarve fra for at definere konkrete class loadere. Den vigtigste funktion i klassen er loadClass. Den bruges til at indl\u00e6se en klasse. Dern\u00e6st bliver metoden resolveClass kaldt \u2013 dette sker automatisk, hvis man angiver true som den anden parameter i kaldet til loadClass. resolveClass s\u00f8rger for, at man kan instantiere klassen og kalde metoder p\u00e5 den.<\/p>\n<p>&nbsp;<\/p>\n<p>Den mest interessante funktion i ClassLoader er imidlertid defineClass. Den konverterer et byte-array til en klasse. Det vil sige, at man kan indl\u00e6se en klasses bin\u00e6re kode gennem for eksempel en stream, og derefter konvertere dataene til en klasse. Det betyder, at man kan lave en class loader, der henter klasser p\u00e5 en anden computer ved at f\u00f8lge nedenst\u00e5ende r\u00e5skitse til en plan:<\/p>\n<p>&nbsp;<\/p>\n<ol>\n<li>Opret en klasse, der nedarver fra ClassLoader.<\/li>\n<li>Defin\u00e9r metoden loadClass.<\/li>\n<\/ol>\n<p>2.1.\u00a0\u00a0 Opret en stream til class-filen p\u00e5 den anden computer.<\/p>\n<p>2.2.\u00a0\u00a0 Indl\u00e6s class-filen i et array af bytes.<\/p>\n<p>2.3.\u00a0\u00a0 Konverter byte-arrayet til et Class-objekt ved hj\u00e6lp af defineClass-metoden.<\/p>\n<p>2.4.\u00a0\u00a0 Return\u00e9r det Class-objekt, kaldet til defineClass returnerede.<\/p>\n<ol>\n<li>Defin\u00e9r \u00f8vrige metoder for at g\u00f8re implementationen af ClassLoader konkret.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Ovenst\u00e5ende k\u00f8replan er \u2013 skal det \u00e6rligt indr\u00f8mmes \u2013 temmelig overodnet, men i hovedtr\u00e6k er det, det eneste man skal g\u00f8re, for at definere en ny class loader.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h1>Andre muligheder<\/h1>\n<p>&nbsp;<\/p>\n<p>Man kan imidlertid andet med klasser end at instantiere dem og kalde funktioner p\u00e5 dem. Man kan bruge Class-klassens funktioner til at samle en masse informationer om et objekt. ClassInfo-klassen viser, hvordan man kan indsamle oplysninger om en klasse:<\/p>\n<p>&nbsp;<\/p>\n<p>import java.lang.reflect.Modifier;<\/p>\n<p>import java.lang.reflect.Field;<\/p>\n<p>import java.lang.reflect.Method;<\/p>\n<p>import java.lang.reflect.Constructor;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>import java.io.BufferedReader;<\/p>\n<p>import java.io.IOException;<\/p>\n<p>import java.io.InputStreamReader;<\/p>\n<p>&nbsp;<\/p>\n<p>public class ClassInfo<\/p>\n<p>{<\/p>\n<p>private static String describeModifiers (int modifier)<\/p>\n<p>{<\/p>\n<p>String s;<\/p>\n<p>&nbsp;<\/p>\n<p>if (Modifier.isPrivate(modifier))<\/p>\n<p>s = &#8220;private &#8220;;<\/p>\n<p>else<\/p>\n<p>if (Modifier.isPublic(modifier))<\/p>\n<p>s = &#8220;public &#8220;;<\/p>\n<p>else<\/p>\n<p>if (Modifier.isProtected(modifier))<\/p>\n<p>s = &#8220;protected &#8220;;<\/p>\n<p>else<\/p>\n<p>s = &#8220;unspecified &#8220;;<\/p>\n<p>&nbsp;<\/p>\n<p>if (Modifier.isStatic(modifier))<\/p>\n<p>s = s + &#8220;static &#8220;;<\/p>\n<p>&nbsp;<\/p>\n<p>if (Modifier.isFinal(modifier))<\/p>\n<p>s = s + &#8220;final &#8220;;<\/p>\n<p>&nbsp;<\/p>\n<p>if (Modifier.isSynchronized(modifier))<\/p>\n<p>s = s + &#8220;synchronized &#8220;;<\/p>\n<p>&nbsp;<\/p>\n<p>if (Modifier.isVolatile(modifier))<\/p>\n<p>s = s + &#8220;volatile &#8220;;<\/p>\n<p>&nbsp;<\/p>\n<p>if (Modifier.isTransient(modifier))<\/p>\n<p>s = s + &#8220;transient &#8220;;<\/p>\n<p>&nbsp;<\/p>\n<p>if (Modifier.isNative(modifier))<\/p>\n<p>s = s + &#8220;native &#8220;;<\/p>\n<p>&nbsp;<\/p>\n<p>return s;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public static void getClassInfo (String name) throws ClassNotFoundException<\/p>\n<p>{<\/p>\n<p>Class cl = Class.forName (name);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (&#8220;Information om &#8221; + name);<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Generel information om klassen<\/p>\n<p>&nbsp;<\/p>\n<p>if (cl.isInterface())<\/p>\n<p>System.out.println (name + &#8221; er et interface.&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>else<\/p>\n<p>if (cl.isArray())<\/p>\n<p>System.out.println (name + &#8221; er et array af typen &#8221; + cl.getComponentType().getName());<\/p>\n<p>else<\/p>\n<p>if (cl.isPrimitive())<\/p>\n<p>System.out.println (name + &#8221; er en primitiv type.&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Modifier<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println ();<\/p>\n<p>&nbsp;<\/p>\n<p>int modifier = cl.getModifiers();<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (Modifier.isPublic(modifier) ? &#8220;X&#8221; : &#8220;O&#8221;);<\/p>\n<p>System.out.println (&#8221; Public&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (Modifier.isPrivate(modifier) ? &#8220;X&#8221; : &#8220;O&#8221;);<\/p>\n<p>System.out.println (&#8221; Private&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (Modifier.isProtected(modifier) ? &#8220;X&#8221; : &#8220;O&#8221;);<\/p>\n<p>System.out.println (&#8221; Protected&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (Modifier.isStatic(modifier) ? &#8220;X&#8221; : &#8220;O&#8221;);<\/p>\n<p>System.out.println (&#8221; Static&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (Modifier.isFinal(modifier) ? &#8220;X&#8221; : &#8220;O&#8221;);<\/p>\n<p>System.out.println (&#8221; Final&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (Modifier.isAbstract(modifier) ? &#8220;X&#8221; : &#8220;O&#8221;);<\/p>\n<p>System.out.println (&#8221; Abstract&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Nedarvning<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println ();<\/p>\n<p>System.out.println (&#8220;Information om nedarvning:&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (&#8220;Superklasse: &#8221; + cl.getSuperclass());<\/p>\n<p>&nbsp;<\/p>\n<p>Class[] interfaces = cl.getInterfaces();<\/p>\n<p>System.out.print (&#8220;Interfaces: &#8220;);<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; interfaces.length; i++)<\/p>\n<p>System.out.print (interfaces[i].getName() + &#8221; &#8220;);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println();<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Variable<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println ();<\/p>\n<p>System.out.println (&#8220;Variable:&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>Field[] fields = cl.getFields();<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; fields.length; i++)<\/p>\n<p>{<\/p>\n<p>System.out.print (describeModifiers (fields[i].getModifiers()));<\/p>\n<p>System.out.print (fields[i].getType().getName() + &#8221; &#8220;);<\/p>\n<p>System.out.print (fields[i].getName());<\/p>\n<p>System.out.println ();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Constructors<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println ();<\/p>\n<p>System.out.println (&#8220;Constructors&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>Constructor[] constructors = cl.getConstructors();<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; constructors.length; i++)<\/p>\n<p>{<\/p>\n<p>System.out.print (describeModifiers (constructors[i].getModifiers()));<\/p>\n<p>System.out.print (constructors[i].getName() + &#8220;(&#8220;);<\/p>\n<p>Class[] parameters = constructors[i].getParameterTypes();<\/p>\n<p>for (int j = 0; j &lt; parameters.length; j++)<\/p>\n<p>{<\/p>\n<p>System.out.print (parameters[j].getName());<\/p>\n<p>if (j + 1 &lt; parameters.length)<\/p>\n<p>System.out.print (&#8220;, &#8220;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (&#8220;)&#8221;);<\/p>\n<p>Class[] exceptions = constructors[i].getExceptionTypes();<\/p>\n<p>&nbsp;<\/p>\n<p>if (exceptions.length != 0)<\/p>\n<p>System.out.print (&#8221; throws &#8220;);<\/p>\n<p>&nbsp;<\/p>\n<p>for (int j = 0; j &lt; exceptions.length; j++)<\/p>\n<p>{<\/p>\n<p>System.out.print (exceptions[j].getName());<\/p>\n<p>if (j + 1 &lt; exceptions.length)<\/p>\n<p>System.out.print (&#8220;, &#8220;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (&#8220;;&#8221;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Metoder<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println ();<\/p>\n<p>System.out.println (&#8220;Metoder:&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>Method[] methods = cl.getMethods();<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; methods.length; i++)<\/p>\n<p>{<\/p>\n<p>System.out.print (describeModifiers (methods[i].getModifiers()));<\/p>\n<p>System.out.print (methods[i].getReturnType().getName() + &#8221; &#8221; + methods[i].getName() + &#8221; (&#8220;);<\/p>\n<p>Class[] parameters = methods[i].getParameterTypes();<\/p>\n<p>for (int j = 0; j &lt; parameters.length; j++)<\/p>\n<p>{<\/p>\n<p>System.out.print (parameters[j].getName());<\/p>\n<p>if (j + 1 &lt; parameters.length)<\/p>\n<p>System.out.print (&#8220;, &#8220;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Class[] exceptions = methods[i].getExceptionTypes();<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.print (&#8220;)&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>if (exceptions.length != 0)<\/p>\n<p>System.out.print (&#8221; throws &#8220;);<\/p>\n<p>&nbsp;<\/p>\n<p>for (int j = 0; j &lt; exceptions.length; j++)<\/p>\n<p>{<\/p>\n<p>System.out.print (exceptions[j].getName());<\/p>\n<p>if (j + 1 &lt; exceptions.length)<\/p>\n<p>System.out.print (&#8220;, &#8220;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (&#8220;;&#8221;);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[]) throws Exception<\/p>\n<p>{<\/p>\n<p>String className = &#8220;&#8221;;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>System.out.println (&#8220;Indtast navnet p\u00e5 den klasse, der skal diagnosticeres&#8221;);<\/p>\n<p>BufferedReader in = new BufferedReader (new InputStreamReader (System.in));<\/p>\n<p>className = in.readLine();<\/p>\n<p>}<\/p>\n<p>catch (IOException ioe)<\/p>\n<p>{<\/p>\n<p>&nbsp;<\/p>\n<p>System.err.println (&#8220;Fejl under indl\u00e6sning!&#8221;);<\/p>\n<p>System.err.println (ioe.toString());<\/p>\n<p>System.exit (1);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>getClassInfo (className);<\/p>\n<p>}<\/p>\n<p>catch (ClassNotFoundException cnfe)<\/p>\n<p>{<\/p>\n<p>System.err.println (&#8220;Klassen &#8221; + className + &#8221; kunne ikke findes.&#8221;);<\/p>\n<p>System.err.println (cnfe.toString());<\/p>\n<p>System.exit (2);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Klassen lader brugeren indtaste navnet p\u00e5 en klasse, og man vil s\u00e5 blive pr\u00e6senteret for en r\u00e6kke informationer om den p\u00e5g\u00e6ldende klasse. Hvis man for eksempel indtaster java.lang.Integer, f\u00e5r man f\u00f8lgende output:<\/p>\n<p>&nbsp;<\/p>\n<p>Information om java.lang.Integer<\/p>\n<p>&nbsp;<\/p>\n<p>X Public<\/p>\n<p>O Private<\/p>\n<p>O Protected<\/p>\n<p>O Static<\/p>\n<p>X Final<\/p>\n<p>O Abstract<\/p>\n<p>&nbsp;<\/p>\n<p>Information om nedarvning:<\/p>\n<p>Superklasse: class java.lang.Number<\/p>\n<p>Interfaces: java.lang.Comparable<\/p>\n<p>&nbsp;<\/p>\n<p>Variable:<\/p>\n<p>public static final int MIN_VALUE<\/p>\n<p>public static final int MAX_VALUE<\/p>\n<p>public static final java.lang.Class TYPE<\/p>\n<p>&nbsp;<\/p>\n<p>Constructors<\/p>\n<p>public java.lang.Integer(int);<\/p>\n<p>public java.lang.Integer(java.lang.String) throws java.lang.NumberFormatException;<\/p>\n<p>&nbsp;<\/p>\n<p>Metoder:<\/p>\n<p>public static java.lang.Integer decode (java.lang.String) throws java.lang.NumberFormatException;<\/p>\n<p>public static java.lang.Integer getInteger (java.lang.String);<\/p>\n<p>public static java.lang.Integer getInteger (java.lang.String, int);<\/p>\n<p>public static java.lang.Integer getInteger (java.lang.String, java.lang.Integer);<\/p>\n<p>&nbsp;<\/p>\n<p>public static int parseInt (java.lang.String) throws java.lang.NumberFormatException;<\/p>\n<p>public static int parseInt (java.lang.String, int) throws java.lang.NumberFormatException;<\/p>\n<p>public static java.lang.String toBinaryString (int);<\/p>\n<p>public static java.lang.String toHexString (int);<\/p>\n<p>public static java.lang.String toOctalString (int);<\/p>\n<p>public static java.lang.String toString (int);<\/p>\n<p>public static java.lang.String toString (int, int);<\/p>\n<p>public static java.lang.Integer valueOf (java.lang.String) throws java.lang.NumberFormatException;<\/p>\n<p>public static java.lang.Integer valueOf (java.lang.String, int) throws java.lang.NumberFormatException;<\/p>\n<p>public boolean equals (java.lang.Object);<\/p>\n<p>public final native java.lang.Class getClass ();<\/p>\n<p>public int hashCode ();<\/p>\n<p>public final native void notify ();<\/p>\n<p>public final native void notifyAll ();<\/p>\n<p>public java.lang.String toString ();<\/p>\n<p>public final void wait () throws java.lang.InterruptedException;<\/p>\n<p>public final native void wait (long) throws java.lang.InterruptedException;<\/p>\n<p>public final void wait (long, int) throws java.lang.InterruptedException;<\/p>\n<p>public byte byteValue ();<\/p>\n<p>public double doubleValue ();<\/p>\n<p>public float floatValue ();<\/p>\n<p>public int intValue ();<\/p>\n<p>public long longValue ();<\/p>\n<p>public short shortValue ();<\/p>\n<p>public int compareTo (java.lang.Integer);<\/p>\n<p>public int compareTo (java.lang.Object);<\/p>\n<p>&nbsp;<\/p>\n<p>Det f\u00f8rste, der sker i metoden getClassInfo, er, at der oprettes en reference til den p\u00e5g\u00e6ldende klasse. Herefter kaldes en r\u00e6kke is-funktioner, der afg\u00f8r om klassen er et interface, et array eller en primitiv type. Dern\u00e6st bruges getModifiers til at bestemme klassens <em>modifiers<\/em>. Disse angiver for eksempel om klassen er public, protected eller private. Modifiers returneres ikke \u2013 som man kunne tro \u2013 i en instans af Modifier-klassen, men som en int. Man kan herefter bruge Modifier-klassens statiske funktioner til at fortolke betydningen af v\u00e6rdien:<\/p>\n<p>&nbsp;<\/p>\n<p>public class Modifier extends Object<\/p>\n<p>{<\/p>\n<p>public static boolean isAbstract(int);<\/p>\n<p>public static boolean isFinal(int);<\/p>\n<p>public static boolean isInterface(int);<\/p>\n<p>public static boolean isNative(int);<\/p>\n<p>public static boolean isPrivate(int);<\/p>\n<p>public static boolean isProtected(int);<\/p>\n<p>public static boolean isPublic(int);<\/p>\n<p>&nbsp;<\/p>\n<p>public static boolean isStatic(int);<\/p>\n<p>public static boolean isSynchronized(int);<\/p>\n<p>public static boolean isTransient(int);<\/p>\n<p>public static boolean isVolatile(int);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses af funktionslisten, er det de samme modifiers, der bruges ved metoder og variable. Efter udskrivning af modifiers udskriver programmet information om nedarvning. Det vil sige navnet p\u00e5 klassens superklasse samt navnene p\u00e5 eventuelt implementerede interfaces. Programmet udskriver kun navnet p\u00e5 den direkte superklasse, men superklassens eventuelle superklasser kan nemt udskrives ved at lave en l\u00f8kke, der udskriver getSuperClass, indtil denne returnerer null:<\/p>\n<p>&nbsp;<\/p>\n<p>Class c = cl;<\/p>\n<p>while (c.getSuperClass() != null)<\/p>\n<p>{<\/p>\n<p>System.out.println (c.getSuperClass());<\/p>\n<p>c = c.getSuperClass();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Selvom en klasse i Java kun kan nedarve fra \u00e9n klasse, kan den implementere en lang r\u00e6kke interfaces. Derfor returnerer funktionen getInterfaces et array af objekter af klassen Class. Interfaces er jo bare en klasse uden kode.<\/p>\n<p>&nbsp;<\/p>\n<p>Herefter beskriver programmet klassens attributter. En liste over disse kan f\u00e5s ved et kald til funktionen getFields, der returnerer et array af objekter af klassen Field:<\/p>\n<p>&nbsp;<\/p>\n<p>public final class Field extends AccesibleObject implements Member<\/p>\n<p>{<\/p>\n<p>public int getModifiers ();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>For hver variabel kaldes den private funktion describeModifiers, der laver en tekstuel beskrivelse af hver variabel.<\/p>\n<p>&nbsp;<\/p>\n<p>Dern\u00e6st udskrives en oversigt over klassens constructors. Disse returneres af funktionen getConstructors, der returnerer et array af objekter af typen Constructor:<\/p>\n<p>&nbsp;<\/p>\n<p>public final class Constructor extends AccessibleObject implements Member<\/p>\n<p>{<\/p>\n<p>public java.lang.Class[] getExceptionTypes ();<\/p>\n<p>public int getModifiers ();<\/p>\n<p>public java.lang.String getName ();<\/p>\n<p>public java.lang.Class[] getParameterTypes ();<\/p>\n<p>public native java.lang.Object newInstance (java.lang.Object[]) throws<\/p>\n<p>java.lang.InstantiationException, java.lang.IllegalAccessException,<\/p>\n<p>java.lang.IllegalArgumentException,<\/p>\n<p>java.lang.reflect.InvocationTargetException;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>For at finde ud af, hvilke parametre en constructor tager, kan man kalde funktionen getParameterTypes, der returnerer et array af objekter af klassen Class. Ligeledes kan funktionen getExceptionTypes bruges til at finde ud af, hvilke exceptions kaldet af constructoren kan medf\u00f8re. En exception er som bekendt ogs\u00e5 en klasse, og derfor bliver listen over mulige exceptions ogs\u00e5 returneret i et array af Class-objekter.<\/p>\n<p>&nbsp;<\/p>\n<p>Klassens metoder behandles p\u00e5 stort set samme m\u00e5de. En liste over dem hentes ved hj\u00e6lp af funktionen getMethods, der returnerer metoderne i et array af Method-objekter:<\/p>\n<p>&nbsp;<\/p>\n<p>public class Method extends AccessibleObject implements Member {<\/p>\n<p>public java.lang.Class[] getExceptionTypes ();<\/p>\n<p>public int getModifiers ();<\/p>\n<p>public java.lang.String getName ();<\/p>\n<p>public java.lang.Class[] getParameterTypes ();<\/p>\n<p>public java.lang.Class getReturnType ();<\/p>\n<p>public native java.lang.Object invoke (java.lang.Object, java.lang.Object[])<\/p>\n<p>throws java.lang.IllegalAccessException,<\/p>\n<p>java.lang.IllegalArgumentException,<\/p>\n<p>java.lang.reflect.InvocationTargetException;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Bortset fra funktionen getReturnType, der returnerer et Class-objekt angivende funktionens returv\u00e6rdi, er funktionerne de samme som ved Constructor-klassen. Dog skal det n\u00e6vnes, at metoder aktiveres ved hj\u00e6lp af invoke, mens constructors kaldes med newInstance.<\/p>\n<p><script type=\"text\/javascript\"><!--\ngoogle_ad_client = \"ca-pub-3400894606969585\";\n\/* Bibliotek - ajp *\/\ngoogle_ad_slot = \"3560879290\";\ngoogle_ad_width = 336;\ngoogle_ad_height = 280;\n\/\/-->\n<\/script><br \/>\n<script type=\"text\/javascript\"\nsrc=\"http:\/\/pagead2.googlesyndication.com\/pagead\/show_ads.js\">\n<\/script><\/p>\n<p>&nbsp;<\/p>\n<h1>Specielle anvendelser af reflections<\/h1>\n<p>&nbsp;<\/p>\n<p>Reflections bliver flittigt brugt i virtuelle Java-maskiner. Hvis man skriver en virtuel Java-maskine (JVM), er det imidlertid ikke nok at kunne instantiere objekter og kalde metoder. Garbage collection er en vigtig del af Java-sproget. Fra og med version 1.2 indeholder Java ogs\u00e5 en r\u00e6kke klasser, der g\u00f8r det lettere at h\u00e5ndtere garbage collection. Disse ligger i pakken java.lang.ref.<\/p>\n<p>&nbsp;<\/p>\n<h2>En programstarter<\/h2>\n<p>En af de opgaver, en virtuel Java-maskine har, er at starte programmer. Da det vil v\u00e6re for omfattende at gennemg\u00e5 en hel virtuel maskine her, vil vi n\u00f8jes med et eksempel p\u00e5, hvordan man kan skrive et program, der kan starte andre Java-programmer. Hvert program startes i sin egen tr\u00e5d, og det er s\u00e5ledes muligt at lade programmet starte flere programmer samtidigt. Gennem en grafisk brugergr\u00e6nseflade er det muligt at angive, hvilket program, der skal startes, samt hvilke parametre, programmet skal startes med.<\/p>\n<p>&nbsp;<\/p>\n<p>Programmet, der kan bruges til at starte de andre programmer, kaldes RunMachine.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>public class RunMachine extends Frame<\/p>\n<p>{<\/p>\n<p>private static RunMachine me;<\/p>\n<p>&nbsp;<\/p>\n<p>private Label classLabel;<\/p>\n<p>public TextField classText;<\/p>\n<p>&nbsp;<\/p>\n<p>private Label argLabel;<\/p>\n<p>public TextField argText;<\/p>\n<p>&nbsp;<\/p>\n<p>private Button start;<\/p>\n<p>private Button stop;<\/p>\n<p>&nbsp;<\/p>\n<p>public RunMachine()<\/p>\n<p>{<\/p>\n<p>super (&#8220;Run Machine&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>setLayout (new GridLayout(3,2));<\/p>\n<p>classLabel = new Label (&#8220;Klasse:&#8221;);<\/p>\n<p>classText = new TextField(20);<\/p>\n<p>&nbsp;<\/p>\n<p>argLabel = new Label (&#8220;Argumenter:&#8221;);<\/p>\n<p>argText = new TextField(20);<\/p>\n<p>&nbsp;<\/p>\n<p>start = new Button (&#8220;Start&#8221;);<\/p>\n<p>start.addActionListener (new StartListener(this));<\/p>\n<p>&nbsp;<\/p>\n<p>stop = new Button (&#8220;Afslut&#8221;);<\/p>\n<p>stop.addActionListener (new StopListener());<\/p>\n<p>&nbsp;<\/p>\n<p>add(classLabel);<\/p>\n<p>add(classText);<\/p>\n<p>&nbsp;<\/p>\n<p>add(argLabel);<\/p>\n<p>add(argText);<\/p>\n<p>&nbsp;<\/p>\n<p>add(start);<\/p>\n<p>add(stop);<\/p>\n<p>&nbsp;<\/p>\n<p>pack();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main(String args[])<\/p>\n<p>{<\/p>\n<p>me = new RunMachine();<\/p>\n<p>me.show();<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Denne del af programmet opretter blot den grafiske brugergr\u00e6nseflade. Et billede af denne kan ses i figur 7-1.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.kristiansborg.dk\/bibliotek\/wp-content\/uploads\/2011\/11\/0701.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-406\" title=\"0701\" src=\"http:\/\/www.kristiansborg.dk\/bibliotek\/wp-content\/uploads\/2011\/11\/0701.png\" alt=\"\" width=\"336\" height=\"96\" srcset=\"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-content\/uploads\/2011\/11\/0701.png 336w, https:\/\/www.kristiansborg.dk\/bibliotek\/wp-content\/uploads\/2011\/11\/0701-300x85.png 300w\" sizes=\"auto, (max-width: 336px) 100vw, 336px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Figur 7-1: Brugergr\u00e6nsefladen i Run Machine-programmet.<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses tilknyttes en action listener til hver af de to knapper. StopListener er den simpleste af de to \u2013 den s\u00f8rger blot for at stoppe programmet, n\u00e5r der trykkes p\u00e5 Afslut-knappen.<\/p>\n<p>&nbsp;<\/p>\n<p>class StopListener implements ActionListener<\/p>\n<p>{<\/p>\n<p>public void actionPerformed (ActionEvent e)<\/p>\n<p>{<\/p>\n<p>System.exit(0);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Mere interessant er klassen StartListener, der h\u00e5ndterer tryk p\u00e5 Start-knappen:<\/p>\n<p>&nbsp;<\/p>\n<p>class StartListener implements ActionListener<\/p>\n<p>{<\/p>\n<p>private RunMachine parent;<\/p>\n<p>&nbsp;<\/p>\n<p>public StartListener(RunMachine parent)<\/p>\n<p>{<\/p>\n<p>this.parent = parent;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void actionPerformed (ActionEvent e)<\/p>\n<p>{<\/p>\n<p>String cl = parent.classText.getText();<\/p>\n<p>String args = parent.argText.getText();<\/p>\n<p>&nbsp;<\/p>\n<p>if (cl.equals(&#8220;&#8221;))<\/p>\n<p>{<\/p>\n<p>System.err.println (&#8220;Ingen klasse angivet.&#8221;);<\/p>\n<p>return;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Kopier parametre til array<\/p>\n<p>&nbsp;<\/p>\n<p>String parameters[] = new String[10];<\/p>\n<p>int i = 0;<\/p>\n<p>int pos = 0;<\/p>\n<p>&nbsp;<\/p>\n<p>while (args.indexOf(&#8221; &#8220;, pos) != -1)<\/p>\n<p>{<\/p>\n<p>parameters[i] = args.substring (pos, args.indexOf(&#8221; &#8220;, pos));<\/p>\n<p>pos = args.indexOf (&#8221; &#8220;, pos);<\/p>\n<p>i++;<\/p>\n<p>&nbsp;<\/p>\n<p>}<\/p>\n<p>parameters[i] = args.substring(pos, args.length());<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Opret tr\u00e5d, der udf\u00f8rer programmet<\/p>\n<p>&nbsp;<\/p>\n<p>RunThread thread = new RunThread (cl, parameters);<\/p>\n<p>thread.start();<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Klassens constructor modtager en reference til RunMachine-klassen, s\u00e5 den kan l\u00e6se de oplysninger, brugeren indtaster. Dette g\u00f8res i actionPerformed-metoden. Her kopieres f\u00f8rst klassen og strengen indeholdende parametrene til lokale variable. Herefter kontrolleres det, om der er indtastet en klasse \u2013 er dette ikke tilf\u00e6ldet, udskrives en fejlmeddelelse.<\/p>\n<p>&nbsp;<\/p>\n<p>Med det p\u00e5 plads kan man koncentrere sig om de vigtigere ting. For eksempel at konvertere de parametre, der skal overf\u00f8res til klassens main-metode fra en tekststreng til et array af Strings. Det g\u00f8res i de efterf\u00f8lgende linier. Bem\u00e6rk, at der her er indsat den begr\u00e6nsning, at der maksimalt kan indtastes 10 parametre. Dette kan naturligvis \u00e6ndres efter behov, eller programmeres dynamisk ved at anvende Vector-klassen. Det sidste, actionPerformed foretager, er at oprette en tr\u00e5d \u2013 RunThread \u2013 som s\u00f8rger for at starte programmet. RunThread er defineret s\u00e5ledes:<\/p>\n<p>&nbsp;<\/p>\n<p>class RunThread extends Thread<\/p>\n<p>{<\/p>\n<p>private String cl;<\/p>\n<p>private String parameters[];<\/p>\n<p>&nbsp;<\/p>\n<p>private Method mainMethod = null;<\/p>\n<p>&nbsp;<\/p>\n<p>public RunThread (String cl, String parameters[])<\/p>\n<p>{<\/p>\n<p>this.cl = cl;<\/p>\n<p>this.parameters = parameters;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void start()<\/p>\n<p>{<\/p>\n<p>Class thisClass = null;<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>thisClass = Class.forName(cl);<\/p>\n<p>}<\/p>\n<p>catch (ClassNotFoundException cnfe)<\/p>\n<p>{<\/p>\n<p>System.err.println (&#8220;Klassen kunne ikke findes: &#8221; + cl);<\/p>\n<p>System.err.println (&#8220;(&#8221; + cl.toString() + &#8220;)&#8221;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Class arguments[] = new Class[1];<\/p>\n<p>&nbsp;<\/p>\n<p>arguments[0] = parameters.getClass();<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>mainMethod = thisClass.getMethod(&#8220;main&#8221;, arguments);<\/p>\n<p>}<\/p>\n<p>catch (NoSuchMethodException nsme)<\/p>\n<p>{<\/p>\n<p>System.err.println (&#8220;Klassen &#8221; + cl + &#8221; indeholder ikke metoden main.&#8221;);<\/p>\n<p>System.err.println (&#8220;(&#8221; + nsme.toString() + &#8220;)&#8221;);<\/p>\n<p>}<\/p>\n<p>run();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void run()<\/p>\n<p>{<\/p>\n<p>Object args[] = new Object[1];<\/p>\n<p>args[0] = parameters;<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>mainMethod.invoke (null, args);<\/p>\n<p>}<\/p>\n<p>catch (IllegalAccessException iae)<\/p>\n<p>{<\/p>\n<p>System.err.println (&#8220;main-metoden er ikke tilg\u00e6ngelig.&#8221;);<\/p>\n<p>System.err.println (&#8220;(&#8221; + iae.toString() + &#8220;)&#8221;);<\/p>\n<p>}<\/p>\n<p>catch (IllegalArgumentException iax)<\/p>\n<p>{<\/p>\n<p>\/\/ Denne exception opst\u00e5r aldrig, da f\u00f8rste parameter i main.invoke er null<\/p>\n<p>}<\/p>\n<p>catch (NullPointerException npe)<\/p>\n<p>{<\/p>\n<p>System.err.println (&#8220;main-metoden er ikke defineret som statisk.&#8221;);<\/p>\n<p>System.err.println (&#8220;(&#8221; + npe.toString() + &#8220;)&#8221;);<\/p>\n<p>}<\/p>\n<p>catch (InvocationTargetException ite)<\/p>\n<p>{<\/p>\n<p>System.err.println (&#8220;main-metoden er defineret forkert.&#8221;);<\/p>\n<p>System.err.println (&#8220;(&#8221; + ite.toString() + &#8220;)&#8221;);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Constructoren i RunThread-klassen modtager b\u00e5de navnet p\u00e5 den klasse, der skal startes, samt det array, der indeholder de parametre, der skal overf\u00f8res til klassens main-metode.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>RunThread er \u2013 som navnet antyder \u2013 en tr\u00e5d, og n\u00e5r denne startes, udf\u00f8res dens start-metode. I denne oprettes der f\u00f8rst en reference til et Class-objekt, der svarer til den klasse, der skal startes. Hvis klassen ikke kunne findes, opst\u00e5r en ClassNotFoundException.<\/p>\n<p>&nbsp;<\/p>\n<p>Herefter oprettes et array \u2013 arguments \u2013 der skal indeholde Class-objekter svarende til de typer, metoden bruger som parametre. I dette tilf\u00e6lde ved vi, at main-metoden kun tager \u00e9n parameter, nemlig et array af Strings. Variablen parameters er netop et String-array, og den kan s\u00e5ledes bruges til at skaffe en reference til et Class-objekt, der angiver et array af Strings. Dette g\u00f8res ved at kalde getClass-metoden p\u00e5 parameters-objektet.<\/p>\n<p>&nbsp;<\/p>\n<p>Det er herefter simpelt at opn\u00e5 en reference til selve main-metoden. Det sker ved hj\u00e6lp af getMethod-metoden. Findes main\u00ad-metoden ikke, opst\u00e5r en NoSuchMethodException, og man kan konludere, at klassen ikke er ment som et selvst\u00e6ndigt Java-program.<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r disse indledende man\u00f8vrer er udf\u00f8rt, overg\u00e5r kontrollen til run-metoden.<\/p>\n<p>&nbsp;<\/p>\n<p>Denne metode starter med at oprette et array af objekter, som skal bruges til at holde de parametre, der skal sendes til main-metoden. Igen ved vi, at det kun drejer sig om et enkelt parameter, og det er derfor sikkert at angive st\u00f8rrelsen af args-arrayet statisk. Man skal passe p\u00e5, at man ikke forfalder til blot at sende parameters-arrayet med som parametre. Dette vil ikke medf\u00f8re en fejl ved kompilering, da et array af Strings sagtens kan konverteres til et array af Objects. Til geng\u00e6ld vil det medf\u00f8re en fejl, n\u00e5r programmet udf\u00f8res, fordi en passende main-metode ikke kan findes. Angiver man for eksempel to parametre til main-funktionen vil programmet lede efter en metode med signaturen main (String, String) og ikke main (String[]), som jo er den rigtige main-metode. Derfor er det vigtigt at oprette et Object-array og l\u00e6gge parametrene heri.<\/p>\n<p>&nbsp;<\/p>\n<p>Herefter skal main-metoden kaldes. Dette g\u00f8res ved at kalde invoke p\u00e5 det mainMethod-objekt, som blev fundet i start-metoden. Det f\u00f8rste parameter i invoke angiver normalt det objekt, metoden skal udf\u00f8res p\u00e5, men da main-metoden altid skal v\u00e6re erkl\u00e6ret statisk, kan man her blot angive null. Det betyder, at man er fri for at instantiere objektet, og fri for at h\u00e5ndtere de exceptions, udf\u00f8rslen af constructoren kan medf\u00f8re. Selvom invoke-kaldet er simpelt, kan der opst\u00e5 en r\u00e6kke exceptions.<\/p>\n<p>&nbsp;<\/p>\n<p>IllegalAccessException opst\u00e5r, hvis main-metoden ikke er public. IllegalArgumentException kan ikke opst\u00e5 i dette tilf\u00e6lde, men den skal alligevel inkluderes i catch-blokken, fordi den er en del af invoke\u2019s throws-blok. Denne exception opst\u00e5r normalt, n\u00e5r metoden ikke eksisterer p\u00e5 det objekt, man fors\u00f8ger at kalde den p\u00e5. Her angives imidlertid intet objekt \u2013 metoden er jo statisk \u2013 og derfor kan denne exception aldrig forekomme. Til geng\u00e6ld kan NullPointerException opst\u00e5. Det sker, hvis main-metoden ikke er defineret statisk som forventet. I s\u00e5 fald vil programmet fors\u00f8ge at udf\u00f8re main-metoden p\u00e5 null, og det medf\u00f8rer naturligvis en NullPointerException. InvocationTargetException opst\u00e5r, hvis de aktuelle og formelle parametre ikke passer sammen. Dette kan kun ske, hvis main-metoden er defineret forkert.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><br \/>\n<\/strong><\/p>\n<h1>Sammenfatning<\/h1>\n<p>&nbsp;<\/p>\n<h1>FAQ<\/h1>\n<p>&nbsp;<\/p>\n<h3>Hvordan bruger man primitive typer i forbindelse med reflections?<\/h3>\n<p><em> <\/em><\/p>\n<p>Primitive typer \u2013 som for eksempel int \u2013 er ikke klasser, og man kan s\u00e5ledes ikke oprette et Class-objekt, der refererer til typen. Til hver primitiv type h\u00f8rer en <em>wrapper-klasse<\/em>, der er en klasse, der indeholder v\u00e6rdier af samme type som den primitive type. Hver af disse klasser \u00ad\u2013 Boolean, Byte, Character, Double, Float, Integer, Long\u00a0 og Short \u2013 har en statisk konstant ved navn TYPE. Denne indeholder et Class-objekt, der svarer til den primitive type, klassen er en wrapper for.<\/p>\n<p>&nbsp;<\/p>\n<p><em>Hvordan opretter man et array dynamisk?<\/em><\/p>\n<p><em> <\/em><\/p>\n<p>java.lang.reflect.Array indeholder de funktioner, der skal bruges til at oprette et array dynamisk. Klassen indeholder to metoder til form\u00e5let:<\/p>\n<p>&nbsp;<\/p>\n<p>public static Object newInstance (Class componentType, int length) throws<\/p>\n<p>NegativeArraySizeException;<\/p>\n<p>&nbsp;<\/p>\n<p>og<\/p>\n<p>&nbsp;<\/p>\n<p>public static Object newInstance (Class componentType, int[] dimensions) throws<\/p>\n<p>IllegalArgumentException, NegativeArraySizeException;<\/p>\n<p>&nbsp;<\/p>\n<p>Den f\u00f8rste bruges, hvis man vil oprette et en-dimensionalt array. Hvis man vil oprette et array med plads til 10 Strings, skriver man alts\u00e5:<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[]) throws<\/p>\n<p>NegativeArraySizeException, ClassNotFoundException<\/p>\n<p>{<\/p>\n<p>Object o = java.lang.reflect.Array.newInstance (<\/p>\n<p>Class.forName (&#8220;java.lang.String&#8221;),10);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Hvis man vil oprette et fler-dimensionalt array, skal man huske p\u00e5, at hver dimension ikke beh\u00f8ver at have den samme l\u00e6ngde. Derfor skal man f\u00f8rst oprette et array af int\u00b8 der angiver l\u00e6ngden af hver dimension. Almindeligvis kan man g\u00f8re det p\u00e5 denne m\u00e5de:<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>String array[][] = new String[3][];<\/p>\n<p>array[0] = new String [4];<\/p>\n<p>array[1] = new String [3];<\/p>\n<p>&nbsp;<\/p>\n<p>array[2] = new String [2];<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Skal det samme opn\u00e5s ved hj\u00e6lp af reflections, skal det g\u00f8res p\u00e5 denne m\u00e5de:<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[]) throws<\/p>\n<p>IllegalArgumentException, NegativeArraySizeException,<\/p>\n<p>ClassNotFoundException<\/p>\n<p>{<\/p>\n<p>int arraySize[] = {4,3,2};<\/p>\n<p>Object array = java.lang.reflect.Array.newInstance (Class.forName<\/p>\n<p>(&#8220;java.lang.String&#8221;), arraySize);<\/p>\n<p>&nbsp;<\/p>\n<p>}<\/p>\n<p><em> <\/em><\/p>\n<p><em>Hvordan tilg\u00e5s elementer i et array?<\/em><\/p>\n<p><em> <\/em><\/p>\n<p>Som det ses af nedenst\u00e5ende signatur indeholder Array-klassen en r\u00e6kke set- og get-funktioner, der kan bruges til at l\u00e6se og \u00e6ndre indholdet af et element i et array.<\/p>\n<p>&nbsp;<\/p>\n<p>public final class Array extends Object<\/p>\n<p>{<\/p>\n<p>public static native byte getByte (java.lang.Object, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native char getChar (java.lang.Object, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>&nbsp;<\/p>\n<p>public static native double getDouble (java.lang.Object, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native float getFloat (java.lang.Object, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native int getInt (java.lang.Object, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native int getLength (java.lang.Object) throws java.lang.IllegalArgumentException;<\/p>\n<p>public static native long getLong (java.lang.Object, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native short getShort (java.lang.Object, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setBoolean (java.lang.Object, int, boolean) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setByte (java.lang.Object, int, byte) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setChar (java.lang.Object, int, char) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setDouble (java.lang.Object, int, double) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setFloat (java.lang.Object, int, float) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setInt (java.lang.Object, int, int) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setLong (java.lang.Object, int, long) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>public static native void setShort (java.lang.Object, int, short) throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Alle metoderne er statiske, og de skal s\u00e5ledes ikke kaldes p\u00e5 selve arrayet \u2013 i stedet skal arrayet sendes med som parameter. Det andet parameter i metodekaldende er det indeks i arrayet, der skal l\u00e6ses eller \u00e6ndres. Kald til metoderne giver mulighed for at tre forskellige exceptions kan opst\u00e5. NullPointerException opst\u00e5r, hvis det array, der angives som parameter, er null. IllegalArgumentException opst\u00e5r, hvis den f\u00f8rste parameter i metodekaldet ikke er et array, mens ArrayIndexOutOfBoundsException opst\u00e5r, hvis indeks angives med en negativ v\u00e6rdi, eller hvis indeks er st\u00f8rre end st\u00f8rrelsen af arrayet. Nedenst\u00e5ende eksempel viser, hvordan et int-array opretets, og hvordan en v\u00e6rdi inds\u00e6ttes i arrayet.<\/p>\n<p>&nbsp;<\/p>\n<p>Object array = java.lang.reflect.Array.newInstance (Integer.TYPE, 5);<\/p>\n<p>java.lang.reflect.Array.setInt(array, 3, 10);<\/p>\n<p>&nbsp;<\/p>\n<p>Eksemplet opretter f\u00f8rst et array med 5 pladser. Herefter s\u00e6ttes den fjerde plads i arrayet \u2013 den med indeks 3 \u2013 til v\u00e6rdien 10.<\/p>\n<p>&nbsp;<\/p>\n<p><em>Hvis en klasses constructor er overloaded, kan man s\u00e5 kalde <\/em><em>constructor.newInstance p\u00e5 en tilf\u00e6ldig constructor i klassen, og ved hj\u00e6lp af parametrene i newInstance-kaldet angive, hvilken constructor, der skal kaldes?<\/em><\/p>\n<p>&nbsp;<\/p>\n<p>Nej. Man skal kalde newInstance p\u00e5 den constructor, der skal udf\u00f8res. Man v\u00e6lger den rigtige constructor ved at foretage et kald til Class.getConstructor().<\/p>\n<p>&nbsp;<\/p>\n<p>Det samme g\u00f8r sig i \u00f8vrigt g\u00e6ldende for metoder, hvor Method.Invoke heller ikke kan bruges til at v\u00e6lge mellem flere forskellige overloadede metoder.<\/p>\n<div style=\"border: 1px solid red; color: red\">\n<b>Du l\u00e6ser en gammel bog<\/b><br \/>\nDen bog, du l\u00e6ser her, er fra 1998, og mange ting kan have \u00e6ndret sig siden da.<br \/>\nVi h\u00e5ber, at du stadig kan finde relevant information i den.<br \/>\nHvis du vil l\u00e6se aktuelle oplysninger om de avancerede dele af Java, anbefaler vi<br \/>\nbogen <a href=\"http:\/\/clk.tradedoubler.com\/click?p(197229)a(2029446)g(19172914)url(http:\/\/www.adlibris.com\/dk\/product.aspx?isbn=0132354799)\"  target=\"_blank\">Core Java &#8211; Advanced Features<\/a><img decoding=\"async\" src=\"http:\/\/impdk.tradedoubler.com\/imp?type(inv)g(19172914)a(2029446)\" \/>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":332,"menu_order":70,"comment_status":"closed","ping_status":"open","template":"","meta":{"_monsterinsights_skip_tracking":false,"footnotes":""},"class_list":["post-405","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"keywords\" content=\"java,reflection,programmering,metodekald\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Biblioteket | Samling af artikler og b\u00f8ger\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Reflections | Biblioteket\" \/>\n\t\t<meta property=\"og:description\" content=\"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2011-11-03T12:47:19+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2011-11-03T12:49:04+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Reflections | Biblioteket\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-7-reflections\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"name\":\"B\\u00f8ger\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"position\":2,\"name\":\"B\\u00f8ger\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/#listItem\",\"name\":\"Avanceret Java-programmering\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/#listItem\",\"position\":3,\"name\":\"Avanceret Java-programmering\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-7-reflections\\\/#listItem\",\"name\":\"Kapitel 7 Reflections\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"name\":\"B\\u00f8ger\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-7-reflections\\\/#listItem\",\"position\":4,\"name\":\"Kapitel 7 Reflections\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/#listItem\",\"name\":\"Avanceret Java-programmering\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#organization\",\"name\":\"Biblioteket\",\"description\":\"Samling af artikler og b\\u00f8ger\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-7-reflections\\\/#webpage\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-7-reflections\\\/\",\"name\":\"Reflections | Biblioteket\",\"description\":\"Reflections er en anderledes m\\u00e5de at kalde metoder p\\u00e5. Normalt skrives navnene p\\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\\u00e5 forh\\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\\u00e5 hvilket tidspunkt, n\\u00e5r programmet k\\u00f8res. Hvis man vil give brugeren mulighed for at v\\u00e6lge mellem flere forskellige genneml\\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \\u2013 mens programmer k\\u00f8rer \\u2013 indtaste navnet p\\u00e5 en metode, og s\\u00e5 f\\u00e5 den udf\\u00f8rt.\",\"inLanguage\":\"da-DK\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-7-reflections\\\/#breadcrumblist\"},\"datePublished\":\"2011-11-03T14:47:19+02:00\",\"dateModified\":\"2011-11-03T14:49:04+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#website\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/\",\"name\":\"Biblioteket\",\"description\":\"Samling af artikler og b\\u00f8ger\",\"inLanguage\":\"da-DK\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Reflections | Biblioteket","description":"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.","canonical_url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/","robots":"max-image-preview:large","keywords":"java,reflection,programmering,metodekald","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek#listItem","position":1,"name":"Home","item":"https:\/\/www.kristiansborg.dk\/bibliotek","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","name":"B\u00f8ger"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","position":2,"name":"B\u00f8ger","item":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/#listItem","name":"Avanceret Java-programmering"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/#listItem","position":3,"name":"Avanceret Java-programmering","item":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/#listItem","name":"Kapitel 7 Reflections"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","name":"B\u00f8ger"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/#listItem","position":4,"name":"Kapitel 7 Reflections","previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/#listItem","name":"Avanceret Java-programmering"}}]},{"@type":"Organization","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#organization","name":"Biblioteket","description":"Samling af artikler og b\u00f8ger","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/"},{"@type":"WebPage","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/#webpage","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/","name":"Reflections | Biblioteket","description":"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.","inLanguage":"da-DK","isPartOf":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#website"},"breadcrumb":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/#breadcrumblist"},"datePublished":"2011-11-03T14:47:19+02:00","dateModified":"2011-11-03T14:49:04+02:00"},{"@type":"WebSite","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#website","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/","name":"Biblioteket","description":"Samling af artikler og b\u00f8ger","inLanguage":"da-DK","publisher":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#organization"}}]},"og:locale":"da_DK","og:site_name":"Biblioteket | Samling af artikler og b\u00f8ger","og:type":"article","og:title":"Reflections | Biblioteket","og:description":"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.","og:url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/","article:published_time":"2011-11-03T12:47:19+00:00","article:modified_time":"2011-11-03T12:49:04+00:00","twitter:card":"summary","twitter:title":"Reflections | Biblioteket","twitter:description":"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt."},"aioseo_meta_data":{"post_id":"405","title":"Reflections | #site_title","description":"Reflections er en anderledes m\u00e5de at kalde metoder p\u00e5. Normalt skrives navnene p\u00e5 de metoder, der skal kaldes, direkte i kildeteksten, inden den kompileres. Det vil sige, at det p\u00e5 forh\u00e5nd er lagt fast, hvilke metoder, der skal kaldes p\u00e5 hvilket tidspunkt, n\u00e5r programmet k\u00f8res. Hvis man vil give brugeren mulighed for at v\u00e6lge mellem flere forskellige genneml\u00f8b af programmet, kan man bruge if eller switch-case til at evaluere brugerens valg og herefter kalde en funktion. Ved hj\u00e6lp af reflections er det imidlertid muligt at skrive programmer, der er mere dynamiske. For eksempel kan brugeren \u2013 mens programmer k\u00f8rer \u2013 indtaste navnet p\u00e5 en metode, og s\u00e5 f\u00e5 den udf\u00f8rt.","keywords":[{"label":"Java","value":"Java"},{"label":"reflection","value":"reflection"},{"label":"programmering","value":"programmering"},{"label":"metodekald","value":"metodekald"}],"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2020-12-21 06:59:15","updated":"2025-06-04 02:17:13","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/\" title=\"B\u00f8ger\">B\u00f8ger<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/\" title=\"Avanceret Java-programmering\">Avanceret Java-programmering<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tKapitel 7 Reflections\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.kristiansborg.dk\/bibliotek"},{"label":"B\u00f8ger","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/"},{"label":"Avanceret Java-programmering","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/"},{"label":"Kapitel 7 Reflections","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-7-reflections\/"}],"_links":{"self":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/comments?post=405"}],"version-history":[{"count":3,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/405\/revisions"}],"predecessor-version":[{"id":408,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/405\/revisions\/408"}],"up":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/332"}],"wp:attachment":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/media?parent=405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}