Introduction to Java Reflection API
Programs are just another kind of data. Source code is text. It is manipulated line by line, or by parsing expressions. Compiled programs are data, too. Integers and strings are bytes in memory that you interpret a certain way. Instructions in methods are just bytes too. No reason why a program can’t inspect itself.
Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine (JVM). It allows you to find out information about any object, including its methods and fields, at run time. One can no longer get away with this called an enabling technology because it supports Java language elements such as: Java Beans, Serialization, and Remote Method Invocation (RMI). JBoss, Tomcat, Eclipse, etc. are reflection-based.
- Construct new class instances and new arrays
- Access and modify fields of objects and classes
- Invoke methods on objects and classes
- Access and modify elements of arrays
Uses of Reflection
- Extensibility Features: An application may make use of external, user-defined classes by creating instances of extensibility objects using their fully-qualified names.
- Class Browsers and Visual Development Environments: A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code.
- Debuggers and Test Tools: Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a discoverable set APIs defined on a class, to insure a high level of code coverage in a test suite.
Drawbacks of Reflection
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it.
- Performance Overhead: Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed.Slower performance than their non-reflective counterparts, should be avoided in sections of code which are called frequently in performance-sensitive applications.
- Security Restrictions: Reflection requires a runtime permission which may not be present when running under a security manager. Code which has to run in a restricted security context, such as in an Applet.
- Exposure of Internals: Since reflection allows code to perform operations that would be illegal in non-reflective code. Accessing private fields and methods, the use of reflection can result in unexpected side-effects. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
Reflection Classes
static Class Class.forName(String className)
Object Class.newInstance()
java.lang.Class
For every type of object, the Java virtual machine instantiates an immutable instance of java.lang.Class. Class objects represent a loaded class. It provides methods to examine the runtime properties of the object
- its methods
- its fields
- its superclass
- the interfaces it implements
- whether it’s an array
It provides the ability to create new classes and objects. Entry point for all of the Reflection APIs
Methods:
- public String getName( ): Returns the name of the class referred to by the Class object.
- public boolean isInterface( ): Returns true if the Class object refers to an interface.
- public boolean isArray( ): Returns true if the Class object refers to an array type.
- public Class getSuperclass( ): Returns the superclass of the current Class object.
- public Class[] getInterfaces( ): Returns array of interface classes implemented by this class.
- public Class[] getClasses( ): Returns array of inner classes within this class.
- public Object newInstance( ): Creates and returns an instance of this class.
- public static Class forName( String name ): Returns a Class object corresponding to a class name (static method)
- public Constructor[] getConstructors( ): Returns an array of all public constructors in the current class. (import java.lang.reflect.Constructor)
- public Method[] getDeclaredMethods( ): Returns an array of all public and private methods declared in the current class or interface. (import java.lang.reflect.Method)
- public Method[] getMethods( ): Returns an array of all public methods in the current class, as well as those in all superclasses and superinterfaces.
Example: Invoking main( )
Calling: main( String[] args ) Simplified, with no error checking:
Class cl = Class.forName( className );
Class[] paramTypes = new Class[] { String[].class };
Method m = cl.getDeclaredMethod( "main", paramTypes );
Object[] args = new Object[] { new String[] { "Breathing", "Fire" } }
m.invoke( null, args );
Invoking a Constructor
Call getConstructor( ), then call newInstance( ) catch InstantiationException
Class c1 = Class.forName("Villain");
Class[] paramTypes = new Class[] {String.class, Integer.TYPE };
Constructor m = c1.getConstructor( paramTypes );
Object[] arguments = new Object[] { "Darth Vader", new Integer(20) };
Villan v = (Villan) m.newInstance(arguments);
The Array Class
public class Array {
// all static methods:
public int getLength( Object arr );
public Object newInstance( Class elements, int length );
public Object get( Object arr, int index );
public void set( Object arr, int index, Object val );
// Various specialized versions, such as...
public int getInt( Object arr, int index );
public void setInt( Object arr, int index, int val );
}
Canine[] kennel = new Canine[10]; . int n = Array.getLength( kennel ); // set the contents of an array element Array.set( kennel, (n-1), new Canine( "Spaniel" ) ); // get an object from the array, determine its class, // and display its value: Object obj = Array.get( kennel, (n-1) ); Class c1 = obj.getClass( ); System.out.println( c1.getName( ) + "-->" + obj.toString( ) );
Two ways to declare an array
// first: Canine kennel = new Canine[10]; // second: Class c1 = Class.forName( "Canine" ); Canine kennel = (Canine[]) Array.newInstance( c1, 10 );
Example: Expanding an array
write a function that receives an arbitrary array, allocates storage for twice the size of the array, copies the data to the new array, and returns the new array.
Question: Why won’t this code work?
public static Object[] doubleArrayBad( Object[] arr )
{
int newSize = arr.length * 2 + 1;
Object[] newArray = new Object[ newSize ];
for( int i = 0; i < arr.length; i++ )
newArray[ i ] = arr[ i ];
return newArray;
}
Answer: This method always returns an array of Object, rather than the type of the array being copied.
public static Object[] doubleArrayBad( Object[] arr )
{
int newSize = arr.length * 2 + 1;
Object[] newArray = new Object[ newSize ];
for( int i = 0; i < arr.length; i++ )
newArray[ i ] = arr[ i ];
return newArray;
}
Use reflection to get the array type:
public Object[] doubleArray( Object[] arr )
{
Class c1 = arr.getClass( );
if( !c1.isArray( ) ) return null;
int oldSize = Array.getLength( arr );
int newSize = oldSize * 2 + 1;
Object[] newArray = (Object[]) Array.newInstance(
c1.getComponentType( ), newSize );
for( int i = 0; i < arr.length; i++ )
newArray[ i ] = arr[ i ];
return newArray;
}
Related Posts
Popular Posts (last 30 days)
- Attendance Management System 1465 view(s)
- Advanced Java Tutorial (For Intermediate) 722 view(s)
- JAVA Graphical User Interface (GUI) 644 view(s)
- Graph Implementation in C++ 492 view(s)
- File Handling using Input-Output Streams in Java 396 view(s)
- Linked lists in C++ 378 view(s)
- UDP Datagram Sockets in Java 326 view(s)
- Sockets and Network Programming in Java 320 view(s)
- Applications of Stack in data structures 313 view(s)
- Circular Linked Lists 293 view(s)







