Reflection - Class Inspector
Contents:
General Information
The Java Reflection API is used for retrieving information about classes during runtime. Several things are pretty simple such as retrieving all the fields which a class declares. However, as soon as generics are involved, life gets a bit more complicated. To learn more details about the Reflection API I created a little Class Inspector which is available under a BSD-style license.
This project is a playground for me. If you use this package, be aware, that a neat and stable public interface is not on my list so far. Things may change every now and then.
If you have any comments or questions about this software, you are welcome to send an email to rsc (at) admadic.de.
Simple Example
Consider the following class:
public class A { Object objectA; Integer integerA; int intA; String [] stringAryA; public A() { super(); } public Object getObjectA() { return objectA; } public void setObjectA(Object objectA) { this.objectA = objectA; } public void workForOverride() { /* nothing to work */ } }
Below is a screenshot of the inspection panel. It displays the information which is available via methods like getDeclaredFields in Class. The nodes have a different background color to indicate their context (class, field, etc.).

How it Works
The class inspector application builds a tree out of the information about a class. The tree is built on demand when the user expands a node. The new nodes are created in a background thread to keep the UI responsive. After the new nodes are created, they are inserted into the tree within the Event Dispatch Thread.
The nodes are named according to the function which retrieved the information. For instance the results returned by getDeclaredFields from Class are stored in a node named declared fields. A node named parameter types represents results from the function getParameterTypes.
Information about a Class instance
Retrieving information about a Class instance is straight forward. Lets take a look at what information is available from this class:
public class SubA extends A { Object objectSubA; Integer integerSubA; int intSubA; public SubA() { super(); } public Object getObjectSubA() { return objectSubA; } public void setObjectSubA(Object objectSubA) { this.objectSubA = objectSubA; } @Override public void workForOverride() { super.workForOverride(); } }
A screenshot of the inspect panel is shown below. With the reflection API we see among other things that there are three fields, three methods, one constructor and that the super class is A. Nothing fancy.

Lets take a look at the workForOverride method (screenshot below). The list of annotations and the list of declared annotations have no elements although the sources contain the @Override annotation. Well, no surprise, because @Override is declared with @Retention(RetentionPolicy.SOURCE) and should not be there in the compiled class files. Again, nothing fancy.

Information about a Class using Generics
Subclass of Parameterized Class
Lets take a look at these classes of which GenA_Int is a sub class of a parameterized class:
public class GenA_Int extends GenA<Integer> { public GenA_Int(Integer value) { super(value); } } public class GenA<T> { T value; public GenA(T value) { super(); this.value = value; } public T getValue() { return value; } public void setValue(T value) { this.value = value; } }
A screenshot of the inspect panel is shown below. The method getSuperClass returns a Class instance - its simple name is GenA. The method getGenericSuperClass returns a ParameterizedType instance which is more interesting. There is a raw type which is the super class GenA. GenA has a type parameter with the name T. The ParameterizedType also contains actual type parameters which in this case is an Integer class. So this is the connection between the type parameter T in GenA and the use of Integer as the type parameter for the super class in the declaration of GenA_Int.

Two Type Parameters
What about two type parameters? Lets look at the source and the screenshot below.
public class GenB<T,S> { T t; S s; public GenB(T t, S s) { super(); this.t = t; this.s = s; } } public class Sub1GenB<T> extends GenB<T,Integer> { public Sub1GenB(T t, Integer s) { super(t, s); } } public class Sub2GenB<S> extends GenB<Integer,S> { public Sub2GenB(Integer t, S s) { super(t, s); } }

Nested Generics
What about "nested generics"? Here we go:
public class Sub3GenB extends GenB<Integer,GenA<String>> { public Sub3GenB(Integer t, GenA<String> s) { super(t, s); } } public class GenB<T,S> { T t; S s; public GenB(T t, S s) { super(); this.t = t; this.s = s; } } public class GenA<T> { T value; public GenA(T value) { super(); this.value = value; } /* some elements left out */ }

BSD-Style License
The BSD License for the admaDIC Reflection - Class Inspector
Copyright (c) 2007 admaDIC GbR. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
All advertising materials mentioning features or use of this
software must display the following acknowledgement:
This product includes software developed by Rainer Schwarze, admaDIC. - Neither the name Rainer Schwarze, admaDIC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Download Binary and Sources
The inspector package is available as a binary and as a source archive. The binary archive contains a jar file which can be started "as usual" (double click on it or execute "java -jar reflection-0.1.0.jar").
The package is provided under a BSD-style license.
Pack / Download Link | Size | MD5 Link and Checksum |
---|---|---|
Binary |
||
reflection-0.1.0-bin.tar.bz2 | 52 kB | md5 file (098308f84e027473a1170845fdd54eea) |
reflection-0.1.0-bin.zip | 52 kB | md5 file (8d6704456a444a3c5e222fdfb804ab51) |
Source |
||
reflection-0.1.0-src.tar.bz2 | 25 kB | md5 file (f849a30cb887802e2c8c4e8867a65c44) |
reflection-0.1.0-src.zip | 112 kB | md5 file (0fbfaf5c3d89758a39b86afce55c2913) |