Sei sulla pagina 1di 24

Java Reflection

By Ken Cooney

http://www.kencooney.com/programming/java/reflection.html

What is Reflection?
Reflection is the ability for a class or object to examine itself. It is possible to find the following information about a class: Constructors Methods Fields Their attributes All this can be done at run time without knowing the classes or methods at compile time. You can dynamically invoke methods and construct new objects.

The Origin of Reflective Programming


The idea of reflection came to Brian Smith in June 1976 at the Xerox Palo Alto Research Center. [1] Smith was working on the KRL representation language and as an exercise to learn the language, he worked on a project to represent KRL in KRL. He reasoned that this would be a good way to learn the language since he had to both use and mention the language. Smith worked on it long enough to become intrigued with the thought of building a system that was self-descriptive. For five years, he worked on the initial versions of such a language. He called it MANTIQ.

A Brief History of Reflection


1982 1983 1984 1987 1987-89? Oct 1996 Feb 1997 Feb 1998 July 2004 Brian Cantwell Smith writes a doctoral dissertation at MIT introducing the notion of computational reflection. 3-LISP is the first official programming language to use reflection.[1] Smalltalk v1.0 has 75% of the standard Reflection command language. [3] The Interim 3-LISP Reference Manual is published, coauthored by Brian Cantwell Smith. [4] Smalltalk v2.0 adds the rest of the Reflection. [3] Perl [5] Visual J++ and C# has reflections. [6] Python v1.4 [7] Java Reflections (JDK v1.1). [8] Python v1.5 makes it easier for reflective programming. [7] PHP v5.0 [9]

Obtaining the class object


We'll first start with the Class: [10] Class classObject = myObject.class; You can specify the class by name: try { // make sure to include the package name, ex: java.util.ArrayList String className = args[0]; Class classObject = Class.forname(className); // do something } catch (ClassNotFoundException e) { e.printStackTrace(); }

Getting the class name and package


You can get the name of the class, including the package: String className = myClass.getName(); You can get the name of the class without the package name: String className = myClass.getSimpleName(); You can just get the package; Package package = myClass.getPackage(); You can get the superclass: Class superClass = myClass.getSuperclass();

Getting the modifiers


You can get the class modifiers (public, private, protected, final, interface, abstract, synchronized, transient, volatile, static). Class classObject = myClass.class; int modifiers = classObject.getModifiers(); if (Modifiers.isPublic(modifiers)) { // do something }

Constructors
Get a list of constructors: Constructor[] constructorArray = classObject.getConstructors(); Get a specific constructor: (paramTypes is type Class[]) Constructor constructor = classObject.getConstructor(paramTypes); Get parameter types for a constructor: Class[] parameterTypes = constructor.getParameterTypes();

Methods
You can get a list of methods: [11] Method[] methodArray = classObject.getMethods(); You can get a single method: (paramTypes is type Class[]) Method method = classObject.getMethod(methodName, paramTypes); You can get the parameter types for the method: Class[] parameterTypes = method.getParameterTypes(); And you can get the return type: Class returnType = method.getReturnType();

Methods continued
Invoking a method: (ArgumentArray is type Object[], theObject can be null if the method is static) Object returnValue = method.invoke(theObject, argumentArray);

Toy example
Back to the Tea factory
package kencooney.com.tea; public class Tea { public String getTeaType() { String teaName = this.getClass().getSimpleName(); return teaName; } }

Toy example (continued)


package kencooney.com.tea; public class GreenTea extends Tea { public void flavor() { } } package kencooney.com.tea; public class OolongTea extends Tea { }

Toy example (continued)


package kencooney.com.tea; public class SimpleTeaFactory { public Tea makeTea(String type) throws TeaException { try { String packageName=this.getClass().getPackage().getName(); type=packageName+"."+type; Class c = Class.forName(type); return (Tea)c.newInstance(); } catch (Throwable e) { throw new TeaException(e); } } }

Toy example (continued)


private static final String GREEN_TEA="GreenTea"; private static final String OOLONG_TEA="OolongTea"; public static void main(String[] arguments) { SimpleTeaFactory teaFactory = new SimpleTeaFactory(); try { ArrayList<Tea> teaArray = new ArrayList<Tea>(); Tea tea = teaFactory.makeTea(GREEN_TEA); teaArray.add(tea); tea = teaFactory.makeTea(OOLONG_TEA); teaArray.add(tea); flavorCheck(teaArray); } catch (TeaException e) { } }

Toy example (continued)


public static void flavorCheck(ArrayList<Tea> teaArray){ for (int i=0; i<teaArray.size();i++) { Tea tea = (Tea)teaArray.get(i); String teaType = tea.getTeaType(); if (teaType.equals(GREEN_TEA)) { GreenTea greenTea = (GreenTea)tea; greenTea.flavor(); System.out.println("Flavored "+teaType+"."); } else { System.out.println("Cannot flavor "+teaType+"."); } } }

Real World Example


I had a project where we had to create different CSV files. We needed to be able to generate any file(s) on demand. Solution: Java Reflections. The file that told the program which reports to run, looked like this: EmployeeTask AccountingTask BusinessTask We passed the filename as the parameter to the executable class. The program would read the file, get the class names, instantiate the class, and then execute the run method (every report had a run method).

Real World Example (continued)


// all this was in a try/catch block inBuffer = new BufferedReader(new FileReader(filename)); while ((line=inBuf.readLine()) != null) { line=line.trim(); StringBuffer name = new StringBuffer(packageName); name.append(line); Class theClass = Class.forName(name.toString); Class parTypes[] = new Class[1]; ParTypes[0] = String.class; Method meth = theClass.getMethod(run, parType); Object theObject = theClass.newInstance(); Object argList[] = new Object[1]; argList[0] = runType; // is this a daily or weekly run? method.invoke(theObject, argList); }

ReflectionHelper
I put together a class I called ReflectionHelper. I used to ideas from the j2ee site on reflection [12] as well as the ClassDeclarationSpy mentioned on Java2s. [13] The program displays the class information, methods, and constructors of any class. If you want the source code, go to: http://www.kencooney.com/programming/java/reflection.html The following pages show the output for java.util.ArrayList.

ReflectionHelper Output
Class: java.util.ArrayList Implemented Interfaces: java.util.List<E> java.util.RandomAccess java.lang.Cloneable java.io.Serializable Inheritance Path: java.util.AbstractList java.util.AbstractCollection java.lang.Object

ReflectionHelper Output (cont.)


Methods: public add(Object) public add(int, Object) public get(int) public clone() public indexOf(Object) public clear() public contains(Object) public isEmpty() public lastIndexOf(Object) public addAll(int, Collection) public addAll(Collection) public size() public toArray(Object[]) public toArray()

ReflectionHelper Output (cont.)


public remove(Object) public remove(int) public set(int, Object) public ensureCapacity(int) public trimToSize() public hashCode() public equals(Object) public iterator() public subList(int, int) public listIterator(int) public listIterator() public toString() public containsAll(Collection) public removeAll(Collection) public retainAll(Collection)

ReflectionHelper Output (cont.)


public final wait() public final wait(long, int) public final native wait(long) public final native getClass() public final native notify() public final native notifyAll()

References
History of Reflective Programming References:
[1] Brian Cantwell Smith. Procedural Reflection in Programming Languages. MIT. http://dspace.mit.edu/handle/1721.1/15961. 1982. [2] Brian Smith. Computational architectures for reasoning. American Journal of Computational Linguistics. Volume 9, number 1, p34. March 1983. http://acl.ldc.upenn.edu/J/J83/J83-1006.pdf . [3] Infoworld July 27, 1987, News Briefs. P31,32 [4] Brian Cantwell Smith, Jim des Rivires. "Interim 3-LISP Reference Manual". Xerox PARC. 1984. [5] The Timeline of Perl and its Culture. http://history.perl.org/PerlTimeline.html [6] Dr. Dobbs M-Dev. C# Versus Java. http://www.ddj.com/windows/184404487. 2001. [7] A. Andersen, A note on reflection in Python 1.5, Distributed Multimedia Research Group Report, MPG-98-05, Lancaster University, UK, March 1998. [8] Joe Weber. Special Edition Using Java 1.1, Third Edition. http://docs.rinet.ru/UJ11/. 1997 [9] php.net. http://www.php.net/manual/en/intro.reflection.php

References (cont.)
Java Reflection Programming References:
[10] Java Platform SE6 Class documentation. http://java.sun.com/javase/6/docs/api/java/lang/Class.html [11] Java Platform SE6 Class documentation. http://java.sun.com/javase/6/docs/api/java/lang/reflect/Method.html [12] Glenn McCluskey. Using Java Reflection. January 1998. http://www.j2ee.me/developer/technicalArticles/ALT/Reflection/index.html [13] Class Declaration Spy. 1995. http://www.java2s.com/Code/Java/Reflection/ClassDeclarationSpy.htm

Potrebbero piacerti anche