{"id":15,"date":"2007-02-17T14:36:05","date_gmt":"2007-02-17T13:36:05","guid":{"rendered":"http:\/\/www.sahits.ch\/blog\/?p=15"},"modified":"2009-01-05T14:11:23","modified_gmt":"2009-01-05T13:11:23","slug":"reflecting-on-java","status":"publish","type":"post","link":"http:\/\/sahits.ch\/blog\/blog\/2007\/02\/17\/reflecting-on-java\/","title":{"rendered":"Reflecting on Java"},"content":{"rendered":"<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\nOft kommt man in die Verlegenheit, dass man eine Methode aufrufen m\u00f6chte, deren Signatur oder Klasse man nicht kennt oder die private ist. Grund daf\u00fcr ist meistens, dass zum Zeitpunkt der Implementierung die relevante Klasse nicht bekannt ist oder die Aufgabe abh\u00e4ngig von verschiedenen Faktoren durch unterschiedliche Klassen erledigt werden muss. Solche und \u00e4hnliche Probleme lassen sich mit dem Package <code>java.lang.reflect<\/code> l\u00f6sen. Doch hier nun zuerst ein Listing der Klasse, \u00fcber die wir reflektieren wollen.\n<\/td>\n<td width=\"50%\" valign=\"top\">\nOften you wish to call a method and you don&#8217;t know the exact signature or class or the method might altogether be private, so you&#8217;re stuck. Such may occure when the implementing class isn&#8217;t known on implementation time or the task may be done by different classes with respect on many factors. Such and similar problems can be solved with the package <code>java.lang.reflect<\/code>. But first let&#8217;s look at te listing of the class on which we will be reflecting:\n<\/td>\n<\/tr>\n<\/table>\n<pre>\r\n1:  public class ReflectionTest {\r\n2:     public int someNumber = 42;\r\n3:     private String hiddenWords = \"Hello world\";\r\n4: \r\n5:     public ReflectionTest(int number, String s){ ... }\r\n6:     public ReflectionTest(int number){ ... }\r\n7: \r\n8:    public int getAnyNumber(){ ... }\r\n9:    public int getAnyNumber(int someInput){ ... }\r\n10:   private void doSomethingSecret() throws Exception { ... }\r\n11:   public static Class getThisClassName() { ... }\r\n12: }\r\n<\/pre>\n<h3>Inspecting the class<\/h3>\n<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\n<\/td>\n<td width=\"50%\" valign=\"top\">\n<\/td>\n<\/tr>\n<\/table>\n<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\nAls Erstes brauchen wir ein Klassen Objekt (Class). Ein solches kann man auf verschiedene Weisen erhalten:<\/p>\n<ul>\n<li>Wenn man ein Objekt der Klasse hat, liefert die Methode <code>getClass()<\/code> das gew\u00fcnsche Objekt.<\/li>\n<li>Wenn die Klasse bekannt ist, kann das Class-Objekt durch anh\u00e4ngen von .class erstellt werden <code>ReflectionTest.class<\/code>. Wenn die Klasse importiert wurde oder <code>full.package.path.ReflectionTest.class<\/code><\/li>\n<li>Wenn man den Namen der Klasse kennt, da er z.B. als Argument \u00fcbergeben wird, kann mit <code>Class.forName (\"full.package. path.ReflectionTest\")<\/code>auf ein Class Objekt zugegriffenwerden. Wenn die Klasse nicht gefunden werden kann, wird eine ClassNotFoundException geworfen. H\u00e4ufig ist die Ursache ein falscher Pfad. Die Klasse muss im Classpath des Programms enthalten sein.\n<\/li>\n<\/ul>\n<\/td>\n<td width=\"50%\" valign=\"top\">\nFirst we need a class object (Class). There are several ways to achieve that:<\/p>\n<ul>\n<li>If you have already an object of the class you can get the class object by calling <code>getClass()<\/code><\/li>\n<li>If the class is known an class object can be obtained by appending .class: <code>ReflectionTest.class<\/code> if the class is in the imports or <code>full.package. path.ReflectionTest.class<\/code> otherwise.<\/li>\n<li>If the name of the class is known, e.g. supplemented by argument, you can get the class object with <code>Class.forName (\"full.package. path.ReflectionTest\")<\/code> When the class cannot be found a ClassNotFoundException is thrown. The cause is often a wrong path. The class has to be in the classpath of the program.<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/table>\n<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\nEine Klasse, wie unser Beispiel, kann Felder oder Variablen besitzen. Es gibt 4 Methoden um Informationen \u00fcber die Felder zu erhalten. <code>getField<\/code> und <code>getFields<\/code> liefern nur \u00f6ffentliche Felder, die nicht Arrays sind. <code>getDeclaredField<\/code> und <code>getDeclaredFields<\/code> liefert die definierten Felder, also insbesondere die nicht \u00f6ffentlichen.\n<\/td>\n<td width=\"50%\" valign=\"top\">\nA class as in our example can contain fields or variables. There are 4 methods to retrive information on these fields. <code>getField<\/code> and <code>getFields<\/code> can provide all public fields that are not arrays. <code>getDeclaredField<\/code> and <code>getDeclaredFields<\/code> provide all difined fields in particular non public fields.\n<\/td>\n<\/tr>\n<\/table>\n<p><code><br \/>\nField f1 = c.getField(\"someNumber\");<br \/>\n\/\/ Instance of the field 'someNumber'<br \/>\nField[] f2 = c.getFields();<br \/>\n\/\/ Array of instances of field. It contains one element:<br \/>\n\/\/ 'someNumber'<br \/>\nField f3 = c.getDeclaredField(\"hiddenWords\");<br \/>\n\/\/ Instance of the field 'hiddenWords'<br \/>\nField[] f4 = c.getDeclaredFields();<br \/>\n\/\/ Array of instances of field. It contains two elements<br \/>\n\/\/ 'someNumber' and 'hiddenWords'<br \/>\n<\/code><\/p>\n<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\nZum Ermitteln der <code>Construktor<\/code>en und <code>Method<\/code>en gibt es analoge Methoden. Bei den Methoden <\/p>\n<ul>\n<li>\n<pre>getDeclaredConstructor<\/pre>\n<\/li>\n<li>\n<pre>getConstructor<\/pre>\n<\/li>\n<li>\n<pre>getDeclaredMethod<\/pre>\n<\/li>\n<li>\n<pre>getMethod<\/pre>\n<\/li>\n<\/ul>\n<p>wird neben dem Namen des Konstruktors\/Methode ein Array von Class Objekten \u00fcbergeben. Diese geben die Typen der Argumente wieder. Wichtig ist zu beachten, dass <code>int.class<\/code> und <code>Integer.class<\/code> nicht denselben Typ repr\u00e4sentieren.\n<\/td>\n<td width=\"50%\" valign=\"top\">\nTo retrive <code>Construktor<\/code>s and <code>Method<\/code>s there are similar methods. In the methods<\/p>\n<ul>\n<li>\n<pre>getDeclaredConstructor<\/pre>\n<\/li>\n<li>\n<pre>getConstructor<\/pre>\n<\/li>\n<li>\n<pre>getDeclaredMethod<\/pre>\n<\/li>\n<li>\n<pre>getMethod<\/pre>\n<\/li>\n<\/ul>\n<p> the  second argument is an array of Class objects indicating the types of the arguments. Its imortant to realise that <code>int.class<\/code> and <code>Integer.class<\/code> are not of the same type.\n<\/td>\n<\/tr>\n<\/table>\n<h3>Method Call<\/h3>\n<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\nHat man die Methode die man aufrufen m\u00f6chte gefunden, so kann man diese \u00fcber <code>invoke<\/code> aufrufen. Wenn die Methode nicht <code>static<\/code>, ist muss erst ein Objekt aufgetrieben werden, auf dem die Methode aufgerufen wird. Ist f\u00fcr die Klasse ein Default Konstruktor (Konstruktor ohne Argumente) definiert, so kann ein Objekt \u00fcber <code>c.newInstance()<\/code> erstellt werden, wobei c das Class Objekt ist.<br \/>\nHat die Methode einen Return Type, so wird dieser zur\u00fcckgegeben. Handelt es sich um einen primitiven Typ, wird ein entsprechender Wrapper zur\u00fcckgegeben (Boxing).<br \/>\nF\u00fcr Konstruktoren ist es etwas einfacher, da diese immer static sind. Somit kann \u00fcber <code>newInstance<\/code> ein neues Objekt erzeugt werden.<br \/>\nSowohl <code>newInstance<\/code> als auch <code>invoke<\/code> haben als letztes Argument ein Objekt-Array in dem die Parameter f\u00fcr den Konstruktor\/Methodenaufruf enthalten sind.\n<\/td>\n<td width=\"50%\" valign=\"top\">\nIs the method which should be called found, it can be executed with a call of <code>invoke<\/code>. If the method is  <code>static<\/code> you need an object on which the method can be executed. If a default constructor (constructor with no arguments) is defined on the class, an object can be obtained by <code>c.newInstance()<\/code> where c is the Class Object.<br \/>\nWhen the method has a return type it is returned. If the return type is a primitive type it is wrapped accordingly (boxing)<br \/>\nConstructors are somewhat easier to handle because they are always static. Therefore a new object can be obtaind by invoking <code>newInstance<\/code><br \/>\nIn both methods (<code>newInstance<\/code> and <code>invoke<\/code>) the last argument is an object array that contains the arguments for the call.\n<\/td>\n<\/tr>\n<\/table>\n<pre>\r\nClass[] types = {int.class};\r\nConstructor con = c.getConstructor(types);\r\nObject[] args = {42};\r\nObject o = con.newInstance(args);\r\nReflectionTest o2 = (ReflectionTest) c.newInstance();\r\n\/\/ Causes InstantiationException because no default\r\n\/\/ constructor is defined\r\nMethod m = c.getMethod(\"getAnyNumber\", types);\r\no = m.invoke(o, args);\r\n\/\/ o is of type Integer\r\nClass[] types2 = {};\r\nObject[] args2 = {};\r\nMethod m2 = c.getMethod(\"getThisClassName\", types2);\r\n\/\/ 'getThisClassName' is a static method\r\nm2.invoke(null, args2);\r\n<\/pre>\n<h3>Private access<\/h3>\n<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\nRichtig n\u00fctzlich werden solche Mechanismen, wenn nicht \u00f6ffentliche Methoden aufgerufen werden m\u00fcssen. Dies ist oft der Fall, wenn ein Unit Test geschrieben wird: Ohne diese Methoden k\u00f6nnen nur \u00f6ffentliche Methoden getestet werden. Um protected Methoden zu testen, muss die Testklasse eine Ableitung sein. Package-Private Methoden k\u00f6nnen nur getestet werden, wenn die Testklasse im selben Package ist. Private Klassen k\u00f6nnen nur getestet werden, wenn die Testklasse eine Innere Klasse ist.<br \/>\nEs gibt gen\u00fcgend Gr\u00fcnde, Methoden in einem objektorientierten Design nicht nach aussen sichtbar zu machen. Auf der anderen Seite sind solche Methoden meistens Bausteine von anderen Methoden. Tests sollten bei der kleinsten Einheit beginnen, um sicher zu stellen, dass die Grundlagen korrekt sind auf denen die Funktionalit\u00e4t aufbaut.<br \/>\nObjekte des Typs <code>Field<\/code>, <code>Method<\/code> oder <code>Constructor<\/code> sind alle von <code>AccessibleObject<\/code> abgeleitet. In dieser Klasse ist die Methode <code>setAccessible<\/code> definiert, mit der die Sichtbarkeit zur Laufzeit auf public gesetzt wird.<\/p>\n<\/td>\n<td width=\"50%\" valign=\"top\">\nRealy usful are these mechanism when you have to call non public methods. That is often the case when you write a unit test on a private method: without these mechanisms only public methods can be testet. Protected methods can be testet if the test class extends the tested class which isn&#8217;t good design. Package private methods can be tested if the test class is in the same package. Private methods can only be tested if the test class is an inner class.<br \/>\nIn an object oriented design there are ample reasons not to make certain methods visible. Such private methodes are used by other more complex methods. Tests should start with the smallest building block to ensure a correct basis on which more functionality is built.<br \/>\nObjects of type <code>Field<\/code>, <code>Method<\/code> or <code>Constructor<\/code> all extend <code>AccessibleObject<\/code>. There the method <code>setAccessible<\/code> is defined. It can be used to set the visibility of methods at runtime to public.\n<\/td>\n<\/tr>\n<\/table>\n<pre>\r\nMethod[] m3 = c.getMethods();\r\nfor (int i = 0; i < m3.length; i++) {\r\n    if (m3[i].getName().equals(\"getThisClassName\")){\r\n        o = con.newInstance(args);\r\n\tm3[i].setAccessible(true);\r\n\tm3[i].invoke(o, args2);\r\n    }\r\n}\r\n<\/pre>\n<table>\n<tr>\n<td width=\"50%\" valign=\"top\">\nDer Source-Code der <a href=\"http:\/\/www.sahits.ch\/blog\/wp-content\/uploads\/2007\/02\/ReflectionTest.java\">Klasse \u00fcber die reflektiert<\/a> wird und der <a href=\"http:\/\/www.sahits.ch\/blog\/wp-content\/uploads\/2007\/02\/Reflect.java\">Beisiel-Code<\/a> ist verf\u00fcgbar.\n<\/td>\n<td width=\"50%\" valign=\"top\">\nThe source code of the <a href=\"http:\/\/www.sahits.ch\/blog\/wp-content\/uploads\/2007\/02\/ReflectionTest.java\">reflected class<\/a> and the <a href=\"http:\/\/www.sahits.ch\/blog\/wp-content\/uploads\/2007\/02\/Reflect.java\">reflecting class<\/a> are available.\n<\/td>\n<\/tr>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>Oft kommt man in die Verlegenheit, dass man eine Methode aufrufen m\u00f6chte, deren Signatur oder Klasse man nicht kennt oder die private ist. Grund daf\u00fcr ist meistens, dass zum Zeitpunkt der Implementierung die relevante Klasse nicht bekannt ist oder die Aufgabe abh\u00e4ngig von verschiedenen Faktoren durch unterschiedliche Klassen erledigt werden muss. Solche und \u00e4hnliche Probleme &hellip; <a href=\"http:\/\/sahits.ch\/blog\/blog\/2007\/02\/17\/reflecting-on-java\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eReflecting on Java\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,6],"tags":[301,300,18,15,25],"class_list":["post-15","post","type-post","status-publish","format-standard","hentry","category-java","category-programmieren","tag-java","tag-programmieren","tag-reflection","tag-source-code","tag-tutorial"],"_links":{"self":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/15","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/comments?post=15"}],"version-history":[{"count":3,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/15\/revisions"}],"predecessor-version":[{"id":295,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/posts\/15\/revisions\/295"}],"wp:attachment":[{"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/media?parent=15"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/categories?post=15"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/sahits.ch\/blog\/wp-json\/wp\/v2\/tags?post=15"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}