Friday, August 17, 2007

Reflections on Java Reflection - part 1

In ordinary life, a reflection is what you see when you look in the mirror. In the world of programming, reflection is what you call it when a program looks at and possibly even modifies its own structure. The Java reflection API allows you to do exactly that by giving you a window into the fundamental features of the language -- classes and fields and methods -- via an ordinary Java API. Understanding reflection will help you understand the tools that you use every day. How does Eclipse manage to do all that helpful auto-completion of method names? How does Tomcat go from a class name in a web.xml file to a running servlet fielding web requests? And how does Spring do all of that magic dependency injection stuff? In your own programs, you can use reflection to write code that is more flexible and dynamic: with reflection your program can cope gracefully with classes it has never met before.
Conjuring Up A Class

As I said, the fundamental idea of reflection is to give you an ordinary Java API into the inner workings of your program. Since the most basic idea in Java is the class (try to write a Java program without one), a good place to start is by looking at the Class class. No, that is not a typing stutter: you can actually get hold of an object which contains everything you might ever need to know about a Java class. That object will have a type of Class. Once you have a Class instance, you can extract all kinds of information about the class from it, including the name of the class, whether it is public or abstract or final, and even its super-class.

Enough theory: let's turn our reflection microscope on the following, very simple Employee class:

package com.russolsen.reflect;

public class Employee
{
public String _firstName;
public String _lastName;
private int _salary;

public Employee()
{
this( "John", "Smith", 50000);
}

public Employee(String fn, String ln, int salary)
{
_firstName = fn;
_lastName = ln;
_salary = salary;
}

public int getSalary()
{
return _salary;
}

public void setSalary(int salary)
{
_salary = salary;
}

public String toString()
{
return "Employee: " + _firstName + " "
+ _lastName + " " + _salary;
}

}

The easiest way to get a class object is to just ask an object instance for its class with the getClass method. The code below creates a Employee instance, asks for its class, and prints out various bits of information about the class:

package com.russolsen.reflect;

import java.lang.reflect.Modifier;

public class GetClassExample
{
public static void main(String[] args)
{

Employee employee = new Employee();

Class klass = employee.getClass();

System.out.println( "Class name: " + klass.getName());
System.out.println(
"Class super class: " + klass.getSuperclass());

int mods = klass.getModifiers();
System.out.println(
"Class is public: " + Modifier.isPublic(mods));
System.out.println(
"Class is final: " + Modifier.isFinal(mods));
System.out.println(
"Class is abstract: " + Modifier.isAbstract(mods));

}

}

Run the code above and you will see something like:

Class name: com.russolsen.reflect.Employee
Class super class: class java.lang.Object
Class is public: true
Class is final: false
Class is abstract: false

No comments: