In this article we will discuss the concept of Java Reflection. Java Reflection is used to determine methods and attributes that will be used in a certain class at runtime.The Reflection in a nutshell, is used to determine methods and attributes that will be used in class (you do not know) at runtime. There are many uses for this type of task, we can mention for example the installation of additional plugins to our developed software.
Imagine if every time a new plugin was developed for the Eclipse , it had to be refactored to adapt to the use of this new plugin. It would be very laborious and impractical, given the amount of plugins that are developed for this IDE. The solution for this is undoubtedly the use of Reflection API. Say for example, strategic points of the system accept the installation of plugins in order to make the system extensible.
</div> <div> <pre>Class unknownClass = UnknownClass.class; for (Field attribute: unknownClass.getDeclaredFields()) { System.out.println (attribute.getName ()); }
Risks of Java Reflection
This feature should be used with care, always paying attention to the possible risks that can be caused by improper use:
- Reduction of Performance: because the code that is being executed is required very often, hence will result in a reduction of performance.
- Problems for security restriction: especially if done in an environment with specific rules.
- Exposure of the internal structure of objects: for using this feature we have access to all methods and attributes of the given object, this can be a problem when it comes to security.
Benefits of Java Reflection
There are also the benefits that can be availed if we use the Java Reflection correctly and appropriately.
- Ease of maintenance
- Minimizing Errors
- Productivity Gain
- Standardization
- Extensibility
Some items are pretty obvious, such as the Productivity Gain, because it is clear that we will not need to rewrite code every time we want to add new features to our system, it is obvious that it has to be ready to receive such ” Coupling “. We consider the extensibility as one of the most important points and beneficiaries of Java Reflection.
Using Java Reflection in the correct way in our system can become more complex (in terms of features). By just adding plugins without messing with any code, it is incredible and extremely powerful.
Some known examples that use the idea of reflection to make your software extensible are tools like Hibernate, Netbeans, Eclipse and among others that enable new plugins to be installed without changing the application code page . Hibernate example uses the Java Reflection to discover fields in our class in order to create the database tables (using the auto-update = ‘true’).
Let us see an example below which creates a class file with several fields and then apply Reflection.
</div> <div> <pre>package net.javabeat; public class File { private String name; private String numberOfCCP; private int quantityOfCCP; private String toHashTable; private boolean performCheckSum; private boolean converterHash; private boolean combineNameNumberCCP; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNumberOfCCP() { return numberOfCCP; } public void setNumberOfCCP(String numberOfCCP) { this.numberOfCCP = numberOfCCP; } public int getQuantityOfCCP() { return quantityOfCCP; } public void setQuantityOfCCP(int quantityOfCCP) { this.quantityOfCCP = quantityOfCCP; } public String getToHashTable() { return toHashTable; } public void setToHashTable(String toHashTable) { this.toHashTable = toHashTable; } public boolean isPerformCheckSum() { return performCheckSum; } public void setPerformCheckSum(boolean performCheckSum) { this.performCheckSum = performCheckSum; } public boolean isConverterHash() { return converterHash; } public void setConverterHash(boolean converterHash) { this.converterHash = converterHash; } public boolean isCombineNameNumberCCP() { return combineNameNumberCCP; } public void setCombineNameNumberCCP(boolean combineNameNumberCCP) { this.combineNameNumberCCP = combineNameNumberCCP; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (combineNameNumberCCP ? 1231 : 1237); result = prime * result + (converterHash ? 1231 : 1237); result = prime * result + ((toHashTable == null) ? 0 : toHashTable.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((numberOfCCP == null) ? 0 : numberOfCCP.hashCode()); result = prime * result + quantityOfCCP; result = prime * result + (performCheckSum ? 1231 : 1237); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; File other = (File) obj; if (combineNameNumberCCP != other.combineNameNumberCCP) return false; if (converterHash != other.converterHash) return false; if (toHashTable == null) { if (other.toHashTable != null) return false; } else if (!toHashTable.equals(other.toHashTable)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (numberOfCCP == null) { if (other.numberOfCCP != null) return false; } else if (!numberOfCCP.equals(other.numberOfCCP)) return false; if (quantityOfCCP != other.quantityOfCCP) return false; if (performCheckSum != other.performCheckSum) return false; return true; } }
Note that we have everything in our class: attributes, getters, setters, hashCode and equals. Now let’s work on it and use the reflection. In the code below, you can follow what is being done step by step with the code comments that are well documented.
Reflection Example Listing 3 : Showing attributes and methods with Reflection
</div> <div> <pre>package net.javabeat; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Main { public static void main(String args[]) { /** * We load the class file through Class.forName which enables us to Load * a class given by a string that must match the Local default class. * This default class is loaded in ClassLoader which is being used by the class * that is running the command. **/ Object fileFromReflection = null; try { fileFromReflection = Class.forName("net.javabeat.File").newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } // Retrieves the class name System.out.println("Class Name:" + fileFromReflection.getClass().getName()); /* * The Class Method of Reflection gives us the possibility to handle All * methods within the loaded object */ System.out.println(""); System.out.println("Methods:"); for (Method m : fileFromReflection.getClass().getMethods()) { System.out.println(m.getName()); } /* * We now capture the attributes of the class. We now have another * important class that use Field class of Reflection. This allows us to * Handle field / fields of our class loaded. */ System.out.println(""); System.out.println("Attributes:"); for (Field f : fileFromReflection.getClass().getDeclaredFields()) { System.out.println(f.getName()); } /* * Note that our approach is very simple, i.e, we are only capturing the * names of methods and attributes, but you can go much further, * capturing the modifiers, types, return and so on. */ } }
Executing the above code gives the following output.
</div> <div> <pre>Class Name:net.javabeat.File Methods: equals hashCode getName setName getNumberOfCCP setNumberOfCCP getQuantityOfCCP setQuantityOfCCP getToHashTable setToHashTable isPerformCheckSum setPerformCheckSum isConverterHash setConverterHash isCombineNameNumberCCP setCombineNameNumberCCP wait wait wait toString getClass notify notifyAll Attributes: name numberOfCCP quantityOfCCP toHashTable performCheckSum converterHash combineNameNumberCCP
Summary
Reference Books:
- Java: The Complete Reference
- Head First Java by Kathy Sierra, Bert Bates
Reflection is useful especially when we are thinking of extensible, hence making the system able to receive new features without requiring code modification.