Java for C# Programmers 9: Reflection

Reflection

Java has full-fledged reflection powers.

    List<Object> ll = new LinkedList<Object>();

    ll.add(13);
    ll.add('A');
    ll.add(true);
    ll.add(3.14);
    ll.add("Java");

    for(Object o: ll)
        System.out.printf("%s -> %s \n", o, o.getClass());

puts out

13 -> class java.lang.Integer 
A -> class java.lang.Character 
true -> class java.lang.Boolean 
3.14 -> class java.lang.Double 
Java -> class java.lang.String 

is / as / instanceof

The is operator in C# has an equivalent in Java: instanceof.
No equivalent for the as operator does exist in Java. You could use this function as a replacement.

public static <T> T as(Class<T> c, Object o)
{
    if(c.isInstance(o))
        return c.cast(o);
    return null;
}

Print Class Information Via Reflection

To print all available information about a type you can use the following class ReflectionInfo.

static public class ReflectionInfo
{
    private static Constructor<?> [] constructors;
    private static Field[] fields;
    private static Method[] methods;

    public static void main(String[] args)
    {
        GetInfo("java.lang.String");
        PrintInfo();
    }

    private static void GetInfo(String className)
    {
        try
        {
            // create class object
            Class cl = Class.forName(className); 
            constructors = cl.getConstructors();
            fields = cl.getDeclaredFields();
            methods = cl.getMethods();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private static void PrintInfo()
    {
        PrintConstructors();
        PrintFields();
        PrintMethods();
    }

    private static void PrintConstructors()
    {
        System.out.println("\nConstructors");
        for(int i = 0; i < constructors.length; ++i)
            System.out.printf("%02d: %s \n", i+1, constructors[i]);
    }

    private static void PrintFields()
    {
        System.out.println("\nFields");
        for(int i = 0; i < fields.length; ++i)
            System.out.printf("%02d: %s \n", i+1, fields[i]);
    }

    private static void PrintMethods()
    {
        System.out.println("\nMethods");
        for(int i = 0; i < methods.length; ++i)
            System.out.printf("%02d: %s \n", i+1, methods[i]);
    }
}

The code above prints the following.

Constructors
01: public java.lang.String(byte[]) 
02: public java.lang.String(byte[],int,int)

    ... (snip) ...

11: public java.lang.String(java.lang.String) 
12: public java.lang.String() 
13: public java.lang.String(byte[],int,int,java.lang.String) 
            throws java.io.UnsupportedEncodingException 
14: public java.lang.String(byte[],int) 
15: public java.lang.String(byte[],int,int,int) 

Fields
01: private final char[] java.lang.String.value 
02: private int java.lang.String.hash 
03: private static final long java.lang.String.serialVersionUID 
04: private static final java.io.ObjectStreamField[] 
            java.lang.String.serialPersistentFields 
05: public static final java.util.Comparator
            java.lang.String.CASE_INSENSITIVE_ORDER 
06: private static final int java.lang.String.HASHING_SEED 
07: private transient int java.lang.String.hash32 

Methods
01: public boolean java.lang.String.equals(java.lang.Object) 
02: public java.lang.String java.lang.String.toString() 
03: public int java.lang.String.hashCode() 
04: public int java.lang.String.compareTo(java.lang.Object) 
05: public int java.lang.String.compareTo(java.lang.String)

    ... (snip) ...

64: public java.lang.String
                   java.lang.String.toUpperCase(java.util.Locale) 
65: public java.lang.String java.lang.String.toUpperCase() 
66: public java.lang.String java.lang.String.trim() 
67: public final void java.lang.Object.wait(long,int) 
            throws java.lang.InterruptedException 
68: public final native void java.lang.Object.wait(long) 
            throws java.lang.InterruptedException 
69: public final void java.lang.Object.wait() 
            throws java.lang.InterruptedException 
70: public final native java.lang.Class 
            java.lang.Object.getClass() 
71: public final native void java.lang.Object.notify() 
72: public final native void java.lang.Object.notifyAll() 

Calling Constructors And Methods via Reflection

Check this example to see how constructors and methods can be called via reflection.

static public class ReflectionInfo
{
    private static Constructor<?>[] constructors;
    private static Field[] fields;
    private static Method[] methods;

    public static void main(String[] args)
    {
        GetInfo("java.lang.String");
        UseReflectedMethods();
    }

    private static void UseReflectedMethods()
    {
        try
        {
            Constructor<?> cons = null;
            // look for the String(String) constructor
            for (Constructor<?> c : constructors)
            {
                if (c.toString().contains("(java.lang.String)"))
                {
                    cons = c;
                    break;
                }
            }

            // Create a new instance of a String 
            // with a String parameter. 
            String s = (String) cons.newInstance("abcde");
            System.out.println(s);    // -> abcde


            Method met = null;
            // look for the concat method
            for (Method m: methods)
            {
                if (m.toString().contains("concat"))
                {
                    met = m;
                    break;
                }
            }

            // Call a method on String s.
            String t = (String) met.invoke(s, " xyz");
            System.out.println(t);    // -> abcde xyz

        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }

    private static void GetInfo(String className)
    {
        try
        {
            // create class object
            Class cl = Class.forName(className); 
            constructors = cl.getConstructors();
            fields = cl.getDeclaredFields();
            methods = cl.getMethods();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

One thought on “Java for C# Programmers 9: Reflection

Comments are closed.