Reflection (which is a feature in Java) allows executing Java program to examine itself (or another code) and manipulate internal properties of the program such as obtaining names of members and perform something on them, like deleting them or displaying them.
By default, every object in Java has getClass() which basically determines the current object’s class (even if unknown at compile time).
Reflection allows you to write programs that are not obliged to “recognize” everything at compile time, but rather it makes the programs dynamic, since they can be linked together at runtime.
A short example of Java Reflection
import java.lang.reflect.*; public class Main { public void print() { System.out.println("print"); } public static void main(String args[]) { try { Class c = Class.forName("java.lang.String"); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) System.out.println(m[i].toString()); } catch (Throwable e) { // manipulate e System.out.println(); } } }
Here class.forName gives us the specified class and after that, it calls getDeclaredMethods which purpose is to retrieve the list of methods that have been defined in the class.
Method m[] stores all the declared methods of the class we are calling this method on, in this case, String.
Try and catch here is needed as if you do not have it, you will get this error:
Output
public boolean java.lang.String.equals(java.lang.Object) public java.lang.String java.lang.String.toString() public int java.lang.String.hashCode() public int java.lang.String.compareTo(java.lang.String) public int java.lang.String.compareTo(java.lang.Object) public int java.lang.String.indexOf(java.lang.String,int) public int java.lang.String.indexOf(java.lang.String) public int java.lang.String.indexOf(int,int) public int java.lang.String.indexOf(int) static int java.lang.String.indexOf(char[],int,int,char[],int,int,int) static int java.lang.String.indexOf(char[],int,int,java.lang.String,int) public static java.lang.String java.lang.String.valueOf(int) public static java.lang.String java.lang.String.valueOf(long) public static java.lang.String java.lang.String.valueOf(float) public static java.lang.String java.lang.String.valueOf(boolean) public static java.lang.String java.lang.String.valueOf(char[]) public static java.lang.String java.lang.String.valueOf(char[],int,int) public static java.lang.String java.lang.String.valueOf(java.lang.Object) public static java.lang.String java.lang.String.valueOf(char) public static java.lang.String java.lang.String.valueOf(double) public char java.lang.String.charAt(int) private static void java.lang.String.checkBounds(byte[],int,int) public int java.lang.String.codePointAt(int) public int java.lang.String.codePointBefore(int) public int java.lang.String.codePointCount(int,int) public int java.lang.String.compareToIgnoreCase(java.lang.String) public java.lang.String java.lang.String.concat(java.lang.String) public boolean java.lang.String.contains(java.lang.CharSequence) public boolean java.lang.String.contentEquals(java.lang.CharSequence) public boolean java.lang.String.contentEquals(java.lang.StringBuffer) public static java.lang.String java.lang.String.copyValueOf(char[]) public static java.lang.String java.lang.String.copyValueOf(char[],int,int) public boolean java.lang.String.endsWith(java.lang.String) public boolean java.lang.String.equalsIgnoreCase(java.lang.String) public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[]) public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]) public void java.lang.String.getBytes(int,int,byte[],int) public byte[] java.lang.String.getBytes(java.nio.charset.Charset) public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException public byte[] java.lang.String.getBytes() public void java.lang.String.getChars(int,int,char[],int) void java.lang.String.getChars(char[],int) private int java.lang.String.indexOfSupplementary(int,int) public native java.lang.String java.lang.String.intern() public boolean java.lang.String.isEmpty() public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.CharSequence[]) public static java.lang.String java.lang.String.join(java.lang.CharSequence,java.lang.Iterable) public int java.lang.String.lastIndexOf(int) public int java.lang.String.lastIndexOf(java.lang.String) static int java.lang.String.lastIndexOf(char[],int,int,java.lang.String,int) public int java.lang.String.lastIndexOf(java.lang.String,int) public int java.lang.String.lastIndexOf(int,int) static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int) private int java.lang.String.lastIndexOfSupplementary(int,int) public int java.lang.String.length() public boolean java.lang.String.matches(java.lang.String) private boolean java.lang.String.nonSyncContentEquals(java.lang.AbstractStringBuilder) public int java.lang.String.offsetByCodePoints(int,int) public boolean java.lang.String.regionMatches(int,java.lang.String,int,int) public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int) public java.lang.String java.lang.String.replace(char,char) public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence) public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String) public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String) public java.lang.String[] java.lang.String.split(java.lang.String) public java.lang.String[] java.lang.String.split(java.lang.String,int) public boolean java.lang.String.startsWith(java.lang.String,int) public boolean java.lang.String.startsWith(java.lang.String) public java.lang.CharSequence java.lang.String.subSequence(int,int) public java.lang.String java.lang.String.substring(int) public java.lang.String java.lang.String.substring(int,int) public char[] java.lang.String.toCharArray() public java.lang.String java.lang.String.toLowerCase(java.util.Locale) public java.lang.String java.lang.String.toLowerCase() public java.lang.String java.lang.String.toUpperCase() public java.lang.String java.lang.String.toUpperCase(java.util.Locale) public java.lang.String java.lang.String.trim()
As you can see from the output, String has quite many methods.
Setting up Reflection
- First, a class object has to be obtained. The most common way of obtaining it, is
Class class = Class.forName("java.lang.'class name, for example String'");
- Next step is to call a method (e.g. getDeclaredMethods(), getFields(), etc.)
- Next step is to use Reflection API to manipulate/change the information
Another example, following the steps above
import java.lang.reflect.*; class Demo { private double exampleVariable; public Demo() { exampleVariable = 2.3; } public void method1() { System.out.println("The instance variable: " + exampleVariable); } public void method2(int n) { System.out.println("The number passed: " + n); } private void method3() { // private method System.out.println("Private method has been called"); } } class Main { public static void main(String args[]) throws Exception { Demo classToBeTested = new Demo(); // creating class object from the class using getClass() Class classObject = classToBeTested.getClass(); System.out.println("Name of class: " + classObject.getName()); // getting the constructor using getConstructor() Constructor constructor = classObject.getConstructor(); System.out.println("Name of constructor: " + constructor.getName()); // stores all the methods the class has Method[] methods = classObject.getMethods(); // printing all method names for (Method method : methods) System.out.println(method.getName()); } }
Output
Name of class: Demo Name of constructor: Demo method1 method2 wait wait wait equals toString hashCode getClass notify notifyAll