Java Reflection Example
Java Reflection API provides the ability to inspect and modify the runtime behavior of applications. Using reflection we can inspect a class or an interface, get their constructors, methods, and fields information at runtime even though the class is not accessible at compile time. We can also use reflection to instantiate an object, invoke it’s methods, change field values. The classes of Reflection API are part of the package java.lang.reflect
and the methods of Reflection API
are parts of the package java.lang.Class
.
1. Introduction
Before we use the capabilities offered by Reflection API, we must first obtain the java.lang.Class
object of the class. If we know the name of the class at compile time, we can do the following:
Class object = classObject.class;
After the creation of the class object, we can use any method of the java.lang.Class
package according to our needs.
2. Technologies used
The example code in this article was built and run using:
- Java 1.8.231(1.8.x will do fine)
- Eclipse IDE for Enterprise Java Developers-Photon
3. Common Methods
3.1 Common methods of java.lang.Class
String getName()
Returns the full name of the entity represented by this Class object, as a String.String getSimpleName()
Returns the simple name of the underlying class as given in the source code.Package getPackage()
Gets the package for this class.Constructor<T>[] getConstructors()
Returns an array containing Constructor objects reflecting all the public constructors of the class represented by this Class object.Constructor<T> getConstructor(Class<?>... parameterTypes)
Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object.Method[] getDeclaredMethods()
Returns an array of Method objects reflecting all the methods declared by the class or interface represented by this Class object.Method[] getMethods()
Returns an array containing Method objects reflecting all the public member methods of the class or interface represented by this Class object, including those declared by the class or interface and those inherited from super-classes and super-interfaces.Field[] getFields()
Returns an array containing Field objects reflecting all the accessible public fields of the class or interface represented by this Class object.Field getField(String name)
Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object.
For further information, you can have a look at java.lang.Class API
.
3.2 Common methods of java.lang.reflect.Constructor
Using Java Reflection API we can inspect the constructors of classes and instantiate objects at runtime. The obtaining of constructor object is achieved by the perspective methods of the class java.lang.reflect.Constructor
.
Specifically, for the instantiation of an object we use the following method:
AnnotatedType getAnnotatedReceiverType​()
Returns anAnnotatedType
object that represents the use of a type to specify the receiver type of the method/constructor represented by thisExecutable
object.AnnotatedType getAnnotatedReturnType​()
Returns anAnnotatedType
object that represents the use of a type to specify the return type of the method/constructor represented by this Executable.<T extends Annotation> T getAnnotation​(Class<T> annotationClass)
Returns this element’s annotation for the specified type if such an annotation is present, else null.Annotation[] getDeclaredAnnotations()
Returns all annotations that are directly present on this element.Annotation[][] getParameterAnnotations()
Returns an array of arrays that represent the annotations on the formal parameters, in declaration order, of the method represented by this Method object.Class<T> getDeclaringClass()
Returns the Class object representing the class that declares the constructor represented by this object.String getName​()
Returns the name of this constructor, as a string.TypeVariable<Constructor<T>>[] getTypeParameters​()
Returns an array of TypeVariable objects that represent the type variables declared by the generic declaration represented by this GenericDeclaration object, in declaration order.void setAccessible​(boolean flag)
Set the accessible flag for this reflected object to the indicated boolean value.T newInstance(Object... args)
Uses the constructor represented by this Constructor object to create and initialize a new instance of the constructor’s declaring class, with the specified initialization parameters.boolean equals(Object obj)
Compares this Method against the specified object.Type[] getGenericExceptionTypes()
Returns an array of Type objects that represent the exceptions declared to be thrown by this Constructor object.Type[] getGenericParameterTypes()
Returns an array of Type objects that represent the formal parameter types, in declaration order, of the method represented by this Constructor object.int hashCode()
Returns a hashcode for this Constructor.boolean isSynthetic()
Returns true if this method is a synthetic method; returns false otherwise.boolean isVarArgs()
Returns true if this method was declared to take a variable number of arguments; returns false otherwise.String toGenericString()
Returns a string describing this Method, including type parameters.String toString()
Returns a string describing this Method.
For further information, you can have a look at java.lang.reflect.Constructor API
.
3.3 Common methods of java.lang.reflect.Method
Using Java Reflection API we can inspect the methods of classes and invoke them at runtime. This is achieved by using the Java class java.lang.reflect.Method
.
String getName()
Returns the name of the method represented by this Method object, as a String.Class[] getParameterTypes()
Returns an array of Class objects that represent the formal parameter types, in declaration order, of the method represented by this Method object.Class getReturnType()
Returns a Class object that represents the formal return type of the method represented by this Method object.Object invoke(Object obj, Object... args)
Invokes the underlying method represented by this Method object, on the specified object with the specified parameters.int getParameterCount()
Returns the number of formal parameters (whether explicitly declared or implicitly declared or neither) for the executable represented by this object.Type getGenericReturnType()
Returns a Type object that represents the formal return type of the method represented by this Method object.Object getDefaultValue()
Returns the default value for the annotation member represented by this Method instance.Type getGenericReturnType()
Returns a Type object that represents the formal return type of the method represented by this Method object.boolean isDefault()
Returns true if this method is a default method; returns false otherwise.boolean isBridge()
Returns true if this method is a bridge method; returns false otherwise.
For further information, you can have a look at java.lang.reflect.Method API
.
3.4 Common methods of java.lang.reflect.Field
Using Java Reflection API we can inspect the fields (member variables) of classes at runtime. This is achieved by using the java class java.lang.reflect.Field
.
String getName()
Returns the name of the field represented by this Field object.Class<?> getType()
Returns a Class object that identifies the declared type for the field represented by this Field object.Object get(Object obj)
Returns the value of the field represented by this Field, on the specified object.boolean isEnumConstant()
Returns true if this field represents an element of an enumerated type; returns false otherwise.Object get(Object obj)
Returns the value of the field represented by this Field, on the specified object.
For further information, you can have a look at java.lang.reflect.Field API
.
3.5 Common methods of java.lang.reflect.Array
The Array class cannot be instantiated and exports static methods to create Java arrays with primitive or class component types, and to get and set array component values.
Object get(Object array, int index)
Returns the value of the indexed component of the specified array object.Object newInstance(Class componentType, int length or dimensions)
Returns a new array with the specified component type and length or dimensions.int getLength(Object array)
Returns the length of the specified array.boolean getBoolean(Object array, int index)
Returns the value of the indexed element in the specified array object, as a boolean.byte getByte(Object array, int index)
Returns the value of the indexed element in the specified array object, as a byte.char getChar(Object array, int index)
Returns the value of the indexed element in the specified array object, as a char.short getShort(Object array, int index)
Returns the value of the indexed element in the specified array object, as a short.int getInt(Object array, int index)
Returns the value of the indexed element in the specified array object, as an int.long getLong(Object array, int index)
Returns the value of the indexed element in the specified array object, as a long.float getFloat(Object array, int index)
Returns the value of the indexed element in the specified array object, as a float.double getDouble(Object array, int index)
Returns the value of the indexed element in the specified array object, as a double.set(Object array, int index, Object value)
Sets the indexed component of the specified array object to the specified new value.setBoolean(Object array, int index, boolean z)
Sets the indexed element of the specified array object to the specified boolean value.setByte(Object array, int index, byte b)
Sets the indexed element of the specified array object to the specified byte value.setChar(Object array, int index, char c)
Sets the indexed element of the specified array object to the specified char value.setShort(Object array, int index, short s)
Sets the indexed component of the specified array object to the specified short value.setInt(Object array, int index, int i)
Sets the indexed component of the specified array object to the specified int value.setLong(Object array, int index, long l)
Sets the indexed component of the specified array object to the specified long value.setFloat(Object array, int index, float f)
Sets the indexed component of the specified array object to the specified float value.setDouble(Object array, int index, double d)
Sets the indexed component of the specified array object to the specified double value.
3.6 Common methods of java.lang.reflect.Modifier
Using Java Reflection API, the Modifier class cannot be instantiated and export static methods or constants that are used to decode the Java language modifiers for classes or members, which are encoded in an integer.
boolean isPublic(int mod)
Returns true if the specified integer includes the public modifier.boolean isPrivate(int mod)
Returns true if the specified integer includes the private modifier.boolean isProtected(int mod)
Returns true if the specified integer includes the protected modifier.boolean isStrict(int mod)
Return true if the integer argument includes the strictfp modifier.boolean isStatic(int mod)
Returns true if the specified integer includes the static modifier.boolean isFinal(int mod)
Returns true if the specified integer includes the final modifier.boolean isSynchronized(int mod)
Returns true if the specified integer includes the synchronized modifier.boolean isVolatile(int mod)
Returns true if the specified integer includes the volatile modifier.boolean isTransient(int mod)
Returns true if the specified integer includes the transient modifier.boolean isNative(int mod)
Returns true if the specified integer includes the native modifier.boolean isInterface(int mod)
Returns true if the specified integer includes the interface modifier.boolean isAbstract(int mod)
Returns true if the specified integer includes the abstract modifier.String toString(int mod)
Returns a string containing a space-separated list of the names of the modifiers included in the specified integer.
4. Java Reflection Example
Create a java class named RentCar.java
with the following code:
RentCar.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package com.javacodegeeks.core.reflection; public class RentCar { private int rate; private String type; public int price; public RentCar( int length) { if (length < 455 ) { type = "small" ; rate = 35 ; } else if ((length >= 455 ) && (length < 495 )) { type = "mid-sized" ; rate = 45 ; } else if (length >= 495 ) { type = "large" ; rate = 55 ; } } public int getRate() { return rate; } public String getType() { return type; } public void setRate( int rate) { this .rate = rate; } public void setType(String type) { this .type = type; } public void computeRentalCost( int numDays) { price = numDays * rate; System.out .println( "The cost of your rental car is " + price + " euros" ); } } |
This class will be called later at runtime.
Now, create another Java class named ReflectionExample.java
with the following code:
ReflectionExample.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | package com.javacodegeeks.core.reflection; import java.lang.reflect.*; import java.util.Arrays; public class ReflectionExample { public static void main(String[] args) { // Obtain the class object if we know the name of the class Class rental = RentCar. class ; try { // get the absolute name of the class String rentalClassPackage = rental.getName(); System.out.println( "Class Name is: " + rentalClassPackage); // get the simple name of the class (without package info) String rentalClassNoPackage = rental.getSimpleName(); System.out.println( "Class Name without package is: " + rentalClassNoPackage); // get the package name of the class Package rentalPackage = rental.getPackage(); System.out.println( "Package Name is: " + rentalPackage); // get all the constructors of the class Constructor[] constructors = rental.getConstructors(); System.out.println( "Constructors are: " + Arrays.toString(constructors)); // get constructor with specific argument Constructor constructor = rental.getConstructor(Integer.TYPE); // initializing an object of the RentCar class RentCar rent = (RentCar) constructor.newInstance( 455 ); // get all methods of the class including declared methods of // superclasses // in that case, superclass of RentCar is the class java.lang.Object Method[] allmethods = rental.getMethods(); System.out.println( "Methods are: " + Arrays.toString(allmethods)); for (Method method : allmethods) { System.out.println( "method = " + method.getName()); } // get all methods declared in the class // but excludes inherited methods. Method[] declaredMethods = rental.getDeclaredMethods(); System.out.println( "Declared Methods are: " + Arrays.toString(declaredMethods)); for (Method dmethod : declaredMethods) { System.out.println( "method = " + dmethod.getName()); } // get method with specific name and parameters Method oneMethod = rental.getMethod( "computeRentalCost" , new Class[] { Integer.TYPE }); System.out.println( "Method is: " + oneMethod); // call computeRentalCost method with parameter int oneMethod.invoke(rent, 4 ); // get all the parameters of computeRentalCost Class[] parameterTypes = oneMethod.getParameterTypes(); System.out.println( "Parameter types of computeRentalCost() are: " + Arrays.toString(parameterTypes)); // get the return type of computeRentalCost Class returnType = oneMethod.getReturnType(); System.out.println( "Return type is: " + returnType); // gets all the public member fields of the class RentCar Field[] fields = rental.getFields(); System.out.println( "Public Fields are: " ); for (Field oneField : fields) { // get public field name Field field = rental.getField(oneField.getName()); String fieldname = field.getName(); System.out.println( "Fieldname is: " + fieldname); // get public field type Object fieldType = field.getType(); System.out.println( "Type of field " + fieldname + " is: " + fieldType); // get public field value Object value = field.get(rent); System.out.println( "Value of field " + fieldname + " is: " + value); } // How to access private member fields of the class // getDeclaredField() returns the private field Field privateField = RentCar. class .getDeclaredField( "type" ); String name = privateField.getName(); System.out.println( "One private Fieldname is: " + name); // makes this private field instance accessible // for reflection use only, not normal code privateField.setAccessible( true ); // get the value of this private field String fieldValue = (String) privateField.get(rent); System.out.println( "fieldValue = " + fieldValue); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } |
Let’s give a short explanation of the above code. Firstly, we obtain the class object of the class RentCar.
Then, we use some methods from the class java.lang.Class
so as to obtain the perspective information from the class RentCar
. Afterwards, we retrieve the constructors of the class RentCar
and we instantiate an object with the integer
455 as parameter. Also, we call two different methods for obtaining the methods provided by the class RentCar
. The difference between the methods getMethods()
and getDeclaredMethods()
is that the first one retrieves all the methods provided by class RentCar
including those methods inherited by the superclasses (in our case, this superclass is java.lang.Object
), while the second one retrieves only the methods provided by our class.
Then, using the methods from the class java.lang.reflect.Method
, we inspect informations of the computeRentalCost()
method.
Afterwards, using the methods from the class java.lang.reflect.Field
, we retrieve information of the public member fields of the class RentCar
. In our case, only field int price
is public.
Finally, we show a way to obtain information for private fields and for that purpose, we use the String type
field which is private.
If we run the above code, we will have the following results:
Output
Class Name is: com.javacodegeeks.core.reflection.RentCar
Class Name without package is: RentCar
Package Name is: package com.javacodegeeks.core.reflection
Constructors are: [public com.javacodegeeks.core.reflection.RentCar(int)]
Methods are: [public void com.javacodegeeks.core.reflection.RentCar.setType(java.lang.String), public void com.javacodegeeks.core.reflection.RentCar.computeRentalCost(int), public int com.javacodegeeks.core.reflection.RentCar.getRate(), public void com.javacodegeeks.core.reflection.RentCar.setRate(int), public java.lang.String com.javacodegeeks.core.reflection.RentCar.getType(), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
method = setType
method = computeRentalCost
method = getRate
method = setRate
method = getType
method = wait
method = wait
method = wait
method = equals
method = toString
method = hashCode
method = getClass
method = notify
method = notifyAll
Declared Methods are: [public void com.javacodegeeks.core.reflection.RentCar.setType(java.lang.String), public void com.javacodegeeks.core.reflection.RentCar.computeRentalCost(int), public int com.javacodegeeks.core.reflection.RentCar.getRate(), public void com.javacodegeeks.core.reflection.RentCar.setRate(int), public java.lang.String com.javacodegeeks.core.reflection.RentCar.getType()]
method = setType
method = computeRentalCost
method = getRate
method = setRate
method = getType
Method is: public void com.javacodegeeks.core.reflection.RentCar.computeRentalCost(int)
The cost of your rental car is 180 euros
Parameter types of computeRentalCost() are: [int]
Return type is: void
Public Fields are:
Fieldname is: price
Type of field price is: int
Value of field price is: 180
One private Fieldname is: type
fieldValue = mid-sized
5. When to use reflection and when you should avoid it
Java Reflection is the process of modifying and analyzing all the capabilities of a class at runtime. Reflection API in Java is used to manipulate class and its members which include fields, methods and constructor at runtime. For example Java Reflection can be used to map properties in JSON files to getter/setter methods in Java objects. Furthermore, Reflection can be used to map the column names of a JDBC ResultSet to getter/setter methods in a Java object.
Nevertheless, we need to be careful using Java Reflection API and sometimes should avoid it. Some reasons are that you can lose the compile-time type safety (you’ll get an error at runtime which might affect end users if you don’t test well enough) or it can cause bugs when refactoring.
6. Pros and Cons
The advantages of the Java Reflections are:
- Debugging: The reflection is used by debuggers to examine private members in classes.
- Extensibility Features: An application may make use of user-defined classes to create instances of extensibility objects using their fully-qualified names.
The disadvantages of the Java Reflections are:
- Exposure of Internals: The reflective code can break abstractions and change the behaviour with upgrades of the platform.
- Performance Overhead: reflective operations have slower performance and for that reason should be avoided in sections of code which are called frequently in performance-sensitive applications.
7. Download the source code
This was a Java Reflection example.
Download the source code here: Java Reflection Example
Last updated on Mar. 23rd, 2020
nice content……