Exploring an Java Object
Java Reflection API’s provides functionality to explore an object(i.e., retrieving the class information of the object). This API is used in Java IDE’s, application server and libraries to operate on unknown objects. The objects loaded at runtime are dynamically analyzed using the Java Reflection API’s.
The following code shows how the Java Reflection API’s can be used to retrieving information. The
public static void exploreObject(Object obj, PrintStream ps)
method takes an Object argument and analyzes it. It displays the class name, the interfaces the class extends, the superclass, the attributes and it’s datatype and the list of all methods complete with their signature.
Also, a sample usage is shown passing an instance of String object.
package com.explore;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ClassExplorer {
public static void main(String[] args) {
exploreObject(new String(), System.out);
}
public static void exploreObject(Object obj, PrintStream ps) {
StringBuilder sb = new StringBuilder();
sb.append("CLASS NAME").append('\n');
sb.append(obj.getClass().getName()).append('\n');
sb.append("#####################################################################").append('\n');
Class<?>[] interfaces = obj.getClass().getInterfaces();
if (interfaces.length != 0) {
sb.append("INTERFACES").append('\n');
for (Class<?> i: interfaces)
sb.append(i.getName()).append('\n');
sb.append("#####################################################################").append('\n');
}
Class<?> superClass = obj.getClass().getSuperclass();
if (superClass != null) {
sb.append("SUPERCLASS").append('\n');
sb.append(superClass.getName()).append('\n');
sb.append("#####################################################################").append('\n');
}
sb.append("ATTRIBUTES").append('\n');
//Get the attributes
Field[] fields = obj.getClass().getDeclaredFields();
for (Field f: fields) {
if (f.getType().getComponentType() != null) {
sb.append(f.getType().getComponentType().getName()).append("[]").append('\t').append(f.getName()).append('\n');
}
else {
sb.append(f.getType().getName()).append('\t').append(f.getName()).append('\n');
}
}
sb.append("#####################################################################").append('\n');
sb.append("METHODS").append('\n');
//Get all methods
Method[] methods = obj.getClass().getDeclaredMethods();
for (Method m: methods) {
//Get the modifier
sb.append(Modifier.toString(m.getModifiers())).append(" ");
//Get the return type of the method
if (m.getReturnType().getComponentType() != null) {
sb.append(m.getReturnType().getComponentType().getName()).append("[] ");
} else {
sb.append(m.getReturnType().getName()).append(" ");
}
//Get the method name
sb.append(m.getName()).append("(");
//Get the parameter list
Class<?>[] parameters = m.getParameterTypes();
if (parameters.length != 0) {
StringBuilder parameterList = new StringBuilder();
for (Class<?> p: parameters) {
if (p.getComponentType() != null) {
parameterList.append(p.getComponentType().getName()).append("[], ");
} else {
parameterList.append(p.getName()).append(", ");
}
}
sb.append(parameterList.substring(0, parameterList.length()-2));
}
sb.append(")");
//Get the exceptions
Class<?>[] exceptions = m.getExceptionTypes();
if (exceptions.length != 0) {
StringBuilder exceptionList = new StringBuilder();
sb.append(" throws ");
for (Class<?> e: exceptions)
exceptionList.append(e.getName()).append(", ");
sb.append(exceptionList.substring(0, (exceptionList.length() - 2)));
}
sb.append(";").append('\n');
}
//Print to the stream
ps.print(sb.toString());
}
}
On executing the above class, the output is
CLASS NAME java.lang.String ##################################################################### INTERFACES java.io.Serializable java.lang.Comparable java.lang.CharSequence ##################################################################### SUPERCLASS java.lang.Object ##################################################################### ATTRIBUTES char[] value int offset int count int hash long serialVersionUID java.io.ObjectStreamField[] serialPersistentFields java.util.Comparator CASE_INSENSITIVE_ORDER ##################################################################### METHODS public int hashCode(); public volatile int compareTo(java.lang.Object); public int compareTo(java.lang.String); public int indexOf(java.lang.String, int); static int indexOf(char[], int, int, char[], int, int, int); public int indexOf(java.lang.String); public int indexOf(int); public int indexOf(int, int); public boolean equals(java.lang.Object); public java.lang.String toString(); public char charAt(int); private static void checkBounds(byte[], int, int); public int codePointAt(int); public int codePointBefore(int); public int codePointCount(int, int); public int compareToIgnoreCase(java.lang.String); public java.lang.String concat(java.lang.String); public boolean contains(java.lang.CharSequence); public boolean contentEquals(java.lang.StringBuffer); public boolean contentEquals(java.lang.CharSequence); public static java.lang.String copyValueOf(char[], int, int); public static java.lang.String copyValueOf(char[]); public boolean endsWith(java.lang.String); public boolean equalsIgnoreCase(java.lang.String); public static transient java.lang.String format(java.lang.String, java.lang.Object[]); public static transient java.lang.String format(java.util.Locale, java.lang.String, java.lang.Object[]); public byte[] getBytes(java.nio.charset.Charset); public byte[] getBytes(); public byte[] getBytes(java.lang.String) throws java.io.UnsupportedEncodingException; public void getBytes(int, int, byte[], int); public void getChars(int, int, char[], int); void getChars(char[], int); public native java.lang.String intern(); public boolean isEmpty(); public int lastIndexOf(java.lang.String); public int lastIndexOf(int); public int lastIndexOf(int, int); static int lastIndexOf(char[], int, int, char[], int, int, int); public int lastIndexOf(java.lang.String, int); public int length(); public boolean matches(java.lang.String); public int offsetByCodePoints(int, int); public boolean regionMatches(int, java.lang.String, int, int); public boolean regionMatches(boolean, int, java.lang.String, int, int); public java.lang.String replace(char, char); public java.lang.String replace(java.lang.CharSequence, java.lang.CharSequence); public java.lang.String replaceAll(java.lang.String, java.lang.String); public java.lang.String replaceFirst(java.lang.String, java.lang.String); public java.lang.String[] split(java.lang.String, int); public java.lang.String[] split(java.lang.String); public boolean startsWith(java.lang.String, int); public boolean startsWith(java.lang.String); public java.lang.CharSequence subSequence(int, int); public java.lang.String substring(int); public java.lang.String substring(int, int); public char[] toCharArray(); public java.lang.String toLowerCase(); public java.lang.String toLowerCase(java.util.Locale); public java.lang.String toUpperCase(); public java.lang.String toUpperCase(java.util.Locale); public java.lang.String trim(); public static java.lang.String valueOf(char[]); public static java.lang.String valueOf(int); public static java.lang.String valueOf(long); public static java.lang.String valueOf(float); public static java.lang.String valueOf(double); public static java.lang.String valueOf(java.lang.Object); public static java.lang.String valueOf(char); public static java.lang.String valueOf(char[], int, int); public static java.lang.String valueOf(boolean);
There are lot of API’s in the Java Reflection package to support more operations. These API’s can be used to analyse objects dynamically.

