From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100274.html | 1025 ++++++++++++++++++++ 1 file changed, 1025 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100274.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100274.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100274.html b/Master/Reference Architectures and Patterns/hjp5/html/k100274.html new file mode 100644 index 0000000..ee97f1d --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100274.html @@ -0,0 +1,1025 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 43 - Reflection +
+
+ + + + +

43.3 Methoden- und Konstruktorenaufrufe

+
+ +
+ + + + +

43.3.1 Parameterlose Methoden

+ +

+Wir wollen uns ein erstes Beispiel für die Anwendung des Reflection-APIs +ansehen. In der Praxis stellt sich immer wieder das Problem, wohin +bei neu entwickelten Klassen der Code zum Testen der Klasse +geschrieben werden soll. Ein Weg ist der, an das Ende der Klasse eine +Methode public static void main +zu hängen und den Testcode dort zu platzieren: + + +

+ + + + +
+ +
+001 public class Queue
+002 {
+003   //...
+004   //Implementierung der Queue
+005   //...
+006 
+007   //---Testcode------------------------------
+008   public static void main(String[] args)
+009   {
+010     Queue q = new Queue();
+011     //...
+012     //Code zum Testen der Queue
+013     //...
+014   }
+015 }
+
+
+ +Listing 43.2: Testcode in der main-Methode

+ +

+Auf diese Weise läßt sich der Testcode einer Dienstleistungsklasse +- wie beispielsweise einer Queue - ganz einfach mit dem Java-Interpreter +aufrufen und reproduzierbar testen. Nachteilig ist natürlich, +dass der eigentliche Code und der Testcode vermischt werden. Dadurch +wird die Klassendatei unnötig groß, was im Hinblick auf +gute Downloadzeiten nicht wünschenswert ist. Besser wäre +es, wenn der Testcode in einer separaten Klasse verbleiben würde. +Wir wollen dazu ein kleines Programm zum Testen von Java-Klassen schreiben. +Es soll folgende Eigenschaften besitzen: +

+ +

+Der Schlüssel zur Implementierung der Klasse Test +liegt in der Anwendung des Reflection-APIs. Das Laden der Testklasse +entspricht dem vorigen Beispiel, zum Aufzählen aller Methoden +bedienen wir uns der Methode getMethods +der Klasse Class: +

+ + + + + +
+ +
+public Method[] getMethods()
+  throws SecurityException
+
+
+
+java.lang.Class
+ +

+getMethods +liefert ein Array von Objekten des Typs Method, +das für jede öffentliche Methode der Klasse ein Element +enthält. Um auch die nicht-öffentlichen Methoden aufzulisten, +kann die Methode getDeclaredMethods +verwendet werden. Die Klasse Method +stellt einige Methoden zum Zugriff auf das Methodenobjekt zur Verfügung. +Die wichtigsten sind: +

+ + + + + +
+ +
+String getName()
+
+int getModifiers()
+
+Class[] getParameterTypes()
+
+Object invoke(Object obj, Object[] args)
+
+
+
+java.lang.reflect.Method
+ +

+Mit getName +kann der Name der Methode ermittelt werden. getModifiers +liefert eine bitverknüpfte Darstellung der Methodenattribute +(static, +private +usw.). Der Rückgabewert kann an die statischen Methoden der Klasse +Modifier +übergeben werden, um festzustellen, welche Attribute die Methode +besitzt: + + + + +

+ + + + + +
+ +
+static boolean isAbstract(int mod)
+static boolean isExplicit(int mod)
+static boolean isFinal(int mod)
+static boolean isInterface(int mod)
+static boolean isNative(int mod)
+static boolean isPrivate(int mod)
+static boolean isProtected(int mod)
+static boolean isPublic(int mod)
+static boolean isStatic(int mod)
+static boolean isStrict(int mod)
+static boolean isSynchronized(int mod)
+static boolean isTransient(int mod)
+static boolean isVolatile(int mod)
+
+
+
+java.lang.reflect.Modifier
+ +

+getParameterTypes +liefert ein Array mit Objekten des Typs Class, +das dazu verwendet werden kann, die Anzahl und Typen der formalen +Argumente der Methode festzustellen. Jedes Array-Element repräsentiert +dabei die Klasse des korrespondierenden formalen Arguments. Hat das +Array die Länge 0, so ist die Methode parameterlos. Gibt es beispielsweise +zwei Elemente mit den Typen String +und Double, +so besitzt die Methode zwei Parameter, die vom Typ String +und Double +sind. + +

+Um auch primitive Typen auf diese Weise darstellen zu können, +gibt es in den Wrapper-Klassen der primitiven Typen (siehe Abschnitt 10.2) +jeweils ein statisches Class-Objekt +mit der Bezeichnung TYPE, +das den zugehörigen primitiven Datentyp bezeichnet. Ein int-Argument +wird also beispielsweise dadurch angezeigt, dass der Rückgabewert +von getParameterTypes +an der entsprechenden Stelle ein Objekt des Typs Integer.TYPE +enthält. Insgesamt gibt es neun derartige +Klassenobjekte, und zwar für die acht primitiven Typen und für +den »leeren« Rückgabewert void: + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Klassenobjekt Typ
Boolean.TYPE +boolean
Character.TYPEchar
Byte.TYPE +byte
Short.TYPE +short
Integer.TYPE +int
Long.TYPE +long
Float.TYPE +float
Double.TYPE +double
Void.TYPE +void
+

+Tabelle 43.1: Klassenobjekte für die primitiven Typen

+

+ + + + + + + + + + + +
+ +

+Alternativ zur .TYPE-Notation kann auch die in Abschnitt 43.3.2 +vorgestellte .class-Notation verwendet werden, um Klassenobjekte für +primitive Typen zu erzeugen. Dazu ist einfach der Name des gewünschten +Typs um ».class« zu ergänzen, also z.B. boolean.class +oder void.class zu schreiben. +Der Compiler erzeugt dann ein passendes Klassenobjekt für den +primitiven Typ.

+ + + + +
 Tipp 
+
+ +

+Die Methode invoke +der Klasse Method +dient dazu, die durch dieses Methodenobjekt repräsentierte Methode +tatsächlich aufzurufen. Das erste Argument obj +gibt dabei das Objekt an, auf dem die Methode ausgeführt werden +soll. Es muss natürlich zu einem Objekt der Klasse gehören, +auf der getMethods +aufgerufen wurde. Das zweite Argument übergibt die aktuellen +Parameter an die Methode. Ähnlich wie bei getParameterTypes +wird auch hier ein Array angegeben, dessen Elemente den korrespondierenden +aktuellen Argumenten entsprechen. Bei Objektparametern ist einfach +ein Objekt des passenden Typs an der gewünschten Stelle zu platzieren. +

+ + + + + + + + + + + +
+ +

+Besitzt die Methode auch primitive Argumente, wird eine automatische +Konvertierung vorgenommen (unwrapping), +indem das entsprechende Array-Element in den passenden primitiven +Datentyp konvertiert wird. Erwartet die Methode beispielsweise ein +int, +so ist ein Integer-Objekt +zu übergeben, das dann beim Aufruf automatisch »ausgepackt« +wird.

+ + + + +
 Tipp 
+
+ +

+Die Implementierung der Klasse Test +sieht so aus: + + +

+ + + + + +
+ +
+001 /* Test.java */
+002 
+003 import java.lang.reflect.*;
+004 
+005 public class Test
+006 {
+007   public static Object createTestObject(String name)
+008   {
+009     //Klassennamen zusammenbauen
+010     int pos = name.lastIndexOf('.');
+011     if (pos == -1) {
+012       name = "Test" + name;
+013     } else {
+014       name = name.substring(0, pos + 1) + "Test" +
+015              name.substring(pos + 1);
+016     }
+017     //Klasse laden
+018     Object ret = null;
+019     try {
+020       Class testclass = Class.forName(name);
+021       //Testobjekt instanzieren
+022       System.out.println("==============================");
+023       System.out.println("Instanzieren von: " + name);
+024       System.out.println("--");
+025       ret = testclass.newInstance();
+026     } catch (ClassNotFoundException e) {
+027       System.err.println("Kann Klasse nicht laden: " + name);
+028     } catch (InstantiationException e) {
+029       System.err.println("Fehler beim Instanzieren: " + name);
+030     } catch (IllegalAccessException e) {
+031       System.err.println("Unerlaubter Zugriff auf: " + name);
+032     }
+033     return ret;
+034   }
+035 
+036   public static void runTests(Object tester)
+037   {
+038     Class clazz = tester.getClass();
+039     Method[] methods = clazz.getMethods();
+040     int cnt = 0;
+041     for (int i = 0; i < methods.length; ++i) {
+042       //Methodenname muss mit "test" anfangen
+043       String name = methods[i].getName();
+044       if (!name.startsWith("test")) {
+045         continue;
+046       }
+047       //Methode muss parameterlos sein
+048       Class[] paras = methods[i].getParameterTypes();
+049       if (paras.length > 0) {
+050         continue;
+051       }
+052       //Methode darf nicht static sein
+053       int modifiers = methods[i].getModifiers();
+054       if (Modifier.isStatic(modifiers)) {
+055         continue;
+056       }
+057       //Nun kann die Methode aufgerufen werden
+058       ++cnt;
+059       System.out.println("==============================");
+060       System.out.println("Aufgerufen wird: " + name);
+061       System.out.println("--");
+062       try {
+063         methods[i].invoke(tester, new Object[0]);
+064       } catch (Exception e) {
+065         System.err.println(e.toString());
+066       }
+067     }
+068     if (cnt <= 0) {
+069       System.out.println("Keine Testmethoden gefunden");
+070     }
+071   }
+072 
+073   public static void main(String[] args)
+074   {
+075     if (args.length <= 0) {
+076       System.err.println("Aufruf: java Test <KlassenName>");
+077       System.exit(1);
+078     }
+079     Object tester = createTestObject(args[0]);
+080     runTests(tester);
+081   }
+082 }
+
+
+Test.java
+ +Listing 43.3: Die Klasse Test

+ +

+Das Hauptprogramm ruft zunächst die Methode createTestObject +auf, um ein Objekt der Testklasse zu generieren. Falls als Argument +also beispielsweise Queue übergeben +wurde, wird ein Objekt des Typs TestQueue +erzeugt. Ist es nicht vorhanden oder kann nicht instanziert werden, +liefert die Methode null +als Rückgabewert. + +

+Anschließend wird das Testobjekt an die Methode runTests +übergeben. Diese besorgt sich das Klassenobjekt und ruft getMethods +auf. Das zurückgegebene Array repräsentiert die Liste aller +öffentlichen Methoden und wird elementweise durchlaufen. Zunächst +wird überprüft, ob der Methodenname mit test +anfängt. Ist das der Fall, wird geprüft, ob die Methode +parameterlos ist und nicht das static-Attribut +besitzt. Sind auch diese Bedingungen erfüllt, kann die Methode +mit invoke +aufgerufen werden. Als erstes Argument wird das Testobjekt übergeben. +Als zweites folgt ein leeres Array des Typs Object, +um anzuzeigen, dass keine Parameter zu übergeben sind. +

+ + + + + + + + + +
+ +

+Beachten Sie, dass am Anfang des Programms das Paket java.lang.reflect +eingebunden wurde. Während die Klassen Class +und Object +aus historischen Gründen in java.lang +liegen (und deshalb automatisch importiert werden), liegen sie für +die übrigen Bestandteile des Reflection-APIs in java.lang.reflect +und müssen deshalb explizit importiert werden.

+ + + + +
 Hinweis 
+
+ +

+Eine beispielhafte Implementierung der Klasse TestQueue +könnte etwa so aussehen: + + +

+ + + + +
+ +
+001 public class TestQueue
+002 {
+003   public TestQueue()
+004   {
+005     //Intialisierungen, z.B. Erzeugen eines zu
+006     //testenden Queue-Objekts
+007   }
+008 
+009   public void test1()
+010   {
+011     //Erste Testmethode
+012   }
+013 
+014   public void test2()
+015   {
+016     //Zweite Testmethode
+017   }
+018 
+019   //...
+020 }
+
+
+ +Listing 43.4: Die Klasse TestQueue

+ +

+Ein Aufruf von + +

+java Test Queue
+
+ + +

+würde nun ein neues Objekt des Typs TestQueue +instanzieren und nacheinander die Methoden test1, +test2 usw. aufrufen. + + + + +

43.3.2 Parametrisierte Methoden

+ +

+In diesem Abschnitt wollen wir uns den Aufruf parametrisierter +Methoden ansehen, was nach den Ausführungen des vorigen Abschnitts +nicht mehr schwierig ist. Als Beispiel soll ein Programm geschrieben +werden, das die in Java nicht vorhandenen Funktionszeiger simuliert. +Es soll eine Methode enthalten, die eine Wertetabelle für eine +mathematische Funktion erzeugt, deren Name als String übergeben +wurde. Nach den Überlegungen des vorigen Abschnitts können +wir uns gleich das Listing ansehen: + + +

+ + + + + +
+ +
+001 /* FloatTables.java */
+002 
+003 import java.lang.reflect.*;
+004 
+005 public class FloatTables
+006 {
+007   public static double times2(double value)
+008   {
+009     return 2 * value;
+010   }
+011 
+012   public static double sqr(double value)
+013   {
+014     return value * value;
+015   }
+016 
+017   public static void printTable(String methname)
+018   {
+019     try {
+020       System.out.println("Wertetabelle fuer " + methname);
+021       int pos = methname.lastIndexOf('.'); 
+022       Class clazz;
+023       if (pos == -1) {
+024         clazz = FloatTables.class;
+025       } else {
+026         clazz = Class.forName(methname.substring(0, pos));
+027         methname = methname.substring(pos + 1);
+028       }
+029       Class[] formparas = new Class[1];
+030       formparas[0] = Double.TYPE;
+031       Method meth = clazz.getMethod(methname, formparas);
+032       if (!Modifier.isStatic(meth.getModifiers())) {
+033         throw new Exception(methname + " ist nicht static");
+034       }
+035       Object[] actargs = new Object[1];
+036       for (double x = 0.0; x <= 5.0; x += 1) {
+037         actargs[0] = new Double(x); 
+038         Double ret = (Double)meth.invoke(null, actargs);
+039         double result = ret.doubleValue();
+040         System.out.println("  " + x + " -> " + result);
+041       }
+042     } catch (Exception e) {
+043       System.err.println(e.toString());
+044     }
+045   }
+046 
+047   public static void main(String[] args)
+048   {
+049     printTable("times2");
+050     printTable("java.lang.Math.exp");
+051     printTable("sqr");
+052     printTable("java.lang.Math.sqrt");
+053   }
+054 }
+
+
+FloatTables.java
+ +Listing 43.5: Funktionszeiger mit Reflection nachbilden

+ +

+Das Hauptprogramm ruft die Methode printTable +viermal auf, um die Wertetabellen zu den statischen Funktionen times2, +java.lang.Math.exp, sqr +und java.lang.Math.sqrt zu erzeugen. +Sie kann sowohl mit lokal definierten Methoden umgehen als auch mit +solchen, die in einer anderen Klasse liegen (in diesem Fall sogar +aus einem anderen Paket). + +

+In Zeile 021 wird zunächst +der am weitesten rechts stehende Punkt im Methodennamen gesucht. Ist +ein Punkt vorhanden, wird der String an dieser Stelle aufgeteilt. +Der links davon stehende Teil wird als Klassenname angesehen, der +rechts davon stehende als Methodenname. Gibt es keinen Punkt, wird +als Klassenname der Name der eigenen Klasse verwendet. Anschließend +wird das zugehörige Klassenobjekt geladen. +

+ + + + + + + + + + + +
+ +

+Ist der Klassenname zur Compilezeit bekannt, kann anstelle des Aufrufs +von forName +die abkürzende Schreibweise .class +verwendet werden. Das hat den Vorteil, dass bereits der Compiler überprüfen +kann, ob die genannte Klasse vorhanden ist.

+ + + + +
 Tipp 
+
+ +

+Anders als im vorigen Abschnitt generiert das Programm nun nicht eine +Liste aller Methoden, sondern sucht mit getMethod +ganz konkret nach einer bestimmten: +

+ + + + + +
+ +
+public Method getMethod(String name, Class[] parameterTypes)
+
+
+
+java.lang.Class
+ +

+Dazu müssen der Name der Methode und eine Beschreibung ihrer +formalen Argumente an getMethod +übergeben werden. Auch hier werden die Argumente durch ein Array +mit korrespondierenden Klassenobjekten repräsentiert. Da die +Methoden, die in diesem Fall aufgerufen werden sollen, nur ein einziges +Argument vom Typ double +haben sollen, hat unsere Parameterspezifikation formParas +lediglich ein einziges Element Double.TYPE. +Wurde keine solche Methode gefunden oder besitzt sie nicht das static-Attribut, +löst getMethods +eine Ausnahme des Typs NoSuchMethodException +aus. +

+ + + + + + + + + + + +
+ +

+Würde die Methode anstelle des primitiven Typs double +ein Argument des Referenztyps Double +erwarten, hätten wir ein Klassenobjekt der Klasse Double +übergeben müssen. Dafür gibt es verschiedene Möglichkeiten, +beispielsweise die beiden folgenden: + +

+formparas[0] = (new Double(0)).getClass();
+
+ + +

+oder + +

+formparas[0] = Double.class;
+
+ +
+ + + + +
 Tipp 
+
+ +

+Auch eine parametrisierte Methode kann mit invoke +aufgerufen werden. Im Unterschied zur parameterlosen muss nun allerdings +ein nicht-leeres Object-Array +mit den aktuellen Argumenten übergeben werden. Hier zeigt sich +ein vermeintliches Problem, denn in einem Array vom Object[] +können keine primitiven Typen abgelegt werden. Um Methoden mit +primitiven Parametern aufrufen zu können, werden diese einfach +in die passende Wrapper-Klasse verpackt (siehe Abschnitt 10.2). +Beim Aufruf von invoke +werden sie dann automatisch »ausgepackt« und dem primitiven +Argument zugewiesen. + +

+Wir verpacken also den zu übergebenden Wert in ein Double-Objekt +und stellen dieses in Zeile 037 +in das Array mit den aktuellen Argumenten. Beim Methodenaufruf in +der nächsten Zeile wird es dann automatisch ausgepackt und steht +innerhalb der Methode als double-Wert +zur Verfügung. Das Programm ruft die Methode für jeden der +Werte 0.0, 1.0, 2.0, 3.0, 4.0 und 5.0 auf und erzeugt so eine einfache +Wertetabelle. +

+ + + + + + + + + +
+ +

+Anders als in Listing 43.3 wird +in diesem Beispiel als erstes Argument von invoke +nicht das Objekt übergeben, an dem die Methode aufgerufen werden +soll, sondern der Wert null. +Das liegt daran, dass wir eine statische Methode aufrufen, +die keiner Objektinstanz, sondern dem Klassenobjekt zugeordnet ist. +Bei nicht-statischen Methoden ist die Übergabe von null +natürlich nicht erlaubt und würde zu einer NullPointerException +führen.

+ + + + +
 Hinweis 
+
+ +

+Die Ausgabe des Programms ist: + +

+Wertetabelle fuer times2
+  0.0 -> 0.0
+  1.0 -> 2.0
+  2.0 -> 4.0
+  3.0 -> 6.0
+  4.0 -> 8.0
+  5.0 -> 10.0
+Wertetabelle fuer java.lang.Math.exp
+  0.0 -> 1.0
+  1.0 -> 2.7182818284590455
+  2.0 -> 7.38905609893065
+  3.0 -> 20.085536923187668
+  4.0 -> 54.598150033144236
+  5.0 -> 148.4131591025766
+Wertetabelle fuer sqr
+  0.0 -> 0.0
+  1.0 -> 1.0
+  2.0 -> 4.0
+  3.0 -> 9.0
+  4.0 -> 16.0
+  5.0 -> 25.0
+Wertetabelle fuer java.lang.Math.sqrt
+  0.0 -> 0.0
+  1.0 -> 1.0
+  2.0 -> 1.4142135623730951
+  3.0 -> 1.7320508075688772
+  4.0 -> 2.0
+  5.0 -> 2.23606797749979
+
+ +

+ + + + + + + + + +
+ +

+Der in Listing 43.5 vorgestellte +Code ist eigentlich nicht zur Nachahmung empfohlen, sondern soll nur +als Beispiel für den Aufruf parametrisierter Methoden mit Hilfe +des Reflection-APIs dienen. Ein zum hier vorgestellten Code äquivalentes +Beispiel auf der Basis von Interfaces wurde in Abschnitt 9.4.3 +vorgestellt.

+ + + + +
 Hinweis 
+
+ + + + +

43.3.3 Parametrisierte Konstruktoren

+ +

+Die Methode newInstance +der Klasse Class +ruft immer den parameterlosen Konstruktor auf, um ein Objekt zu instanzieren. +Mit Reflection ist es aber auch möglich, parametrisierte Konstruktoren +zur dynamischen Instanzierung zu verwenden. Dazu besitzt Class +zwei Methoden getConstructors +und getConstructor, +die dazu verwendet werden, Konstruktorenobjekte zu beschaffen. Anders +als getMethods +und getMethod +liefern sie allerdings kein Objekt des Typs Method, +sondern eines des Typs Constructor +zurück. + +

+Auch dieses besitzt die oben beschriebenen Methoden getModifiers, +getName +und getParameterTypes. +Der Aufruf einer Methode erfolgt allerdings nicht mit invoke, +sondern mit newInstance: +

+ + + + + +
+ +
+Object newInstance(Object[] initargs)
+
+
+
+java.lang.reflect.Constructor
+ +

+newInstance +erwartet ebenfalls ein Array von Argumenten des Typs Object. +Diese werden gegebenenfalls in der zuvor beschriebenen Weise auf primitive +Typen abgebildet und rufen schließlich den passenden Konstruktor +auf. Als Rückgabewert von newInstance +wird das neu instanzierte Objekt geliefert. + +

+Das folgende Listing zeigt die Verwendung parametrisierter Konstruktoren +mit dem Reflection-API: + + +

+ + + + + +
+ +
+001 /* Listing4306.java */
+002 
+003 import java.lang.reflect.*;
+004 
+005 public class Listing4306
+006 {
+007   public static void main(String[] args)
+008   {
+009     Class clazz = TestConstructors.class;
+010     //Formale Parameter definieren
+011     Class[] formparas = new Class[2];
+012     formparas[0] = String.class;
+013     formparas[1] = String.class;
+014     try {
+015       Constructor cons = clazz.getConstructor(formparas);
+016       //Aktuelle Argumente definieren
+017       Object[] actargs = new Object[] {"eins", "zwei"};
+018       Object obj = cons.newInstance(actargs);
+019       ((TestConstructors)obj).print();
+020     } catch (Exception e) {
+021       System.err.println(e.toString());
+022       System.exit(1);
+023     }
+024   }
+025 }
+026 
+027 class TestConstructors
+028 {
+029   private String arg1;
+030   private String arg2;
+031 
+032   public TestConstructors()
+033   {
+034     arg1 = "leer";
+035     arg2 = "leer";
+036   }
+037 
+038   public TestConstructors(String arg1)
+039   {
+040     this();
+041     this.arg1 = arg1;
+042   }
+043 
+044   public TestConstructors(String arg1, String arg2)
+045   {
+046     this();
+047     this.arg1 = arg1;
+048     this.arg2 = arg2;
+049   }
+050 
+051   public void print()
+052   {
+053     System.out.println("arg1 = " + arg1);
+054     System.out.println("arg2 = " + arg2);
+055   }
+056 }
+
+
+Listing4306.java
+ +Listing 43.6: Parametrisierte Konstruktoren mit Reflection aufrufen

+ +

+Das Programm erzeugt zunächst ein Klassenobjekt zu der Klasse +TestConstructors. Anschließend +wird ein Array mit zwei Klassenobjekten der Klasse String +erzeugt und als Spezifikation der formalen Parameter an getConstructor +übergeben. Das zurückgegebene Constructor-Objekt +wird dann mit zwei aktuellen Argumenten »eins« und »zwei« +vom Typ String +ausgestattet, die an seine Methode newInstance +übergeben werden. Diese instanziert das Objekt, castet es auf +die Klasse TestConstructors +und ruft deren Methode print +auf. Die Ausgabe des Programms ist: + +

+arg1 = eins
+arg2 = zwei
+
+ +
+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3