Web Analytics Made
Easy - StatCounter

Menu

About us Contact us

Reflecting on Java Reflection

Tech 2019 / 11 / 14

Reflecting on Java Reflection



What is Java Reflection?

You might have heard about Java Reflection. I used to think that it was complex but later found it to be far simpler and awesome than I had thought. Let’s dive into it.

When Java code is compiled, it is transformed into Java bytecode. As you may already know, JVM (Java Virtual Machine) executes these bytecodes. Sometimes during this execution, some classes, interfaces, fields or methods need to be tested or changed. To serve those changes there are some APIs named Java Reflection API.

By using this API you may make changes in code during runtime by not even knowing the name of the class name, field name or method name during compile time. You will be even accessing private fields or methods using this API.

・・・

Spring Framework, Hibernate, Project Lombok and many other frameworks and libraries are generating code depending on annotation which makes life easier. This code generation is done by using the Java Reflection API. In this post, I will be discussing various classes of java.lang.reflectpackage and just tinker with those a bit.

 

Example:

URL url = new URL("https://monstar-lab.com/global/");
String protocol = url.getProtocol();

System.out.println(protocol);

From the snippet above we can see that I have just made an instance of class URL and called method getProtocol()and printed the output. Now we can see that the decision of which method to call was taken at the compile time. Let’s do the same thing with Reflection API.

Class<?> type = Class.forName("java.net.URL");
Constructor<?> constructor = type.getConstructor(String.class);
Method method = type.getMethod("getProtocol");

Object instance = constructor.newInstance("https://monstar-lab.com/global/");

Object methodCallResult = method.invoke(instance);
System.out.println(methodCallResult);

Now in the snippet above you can see a bit more complex code than the previous one but will be giving you the same result. The interesting part is, in the compile time we did not decide which method to call. We left it to be decided on runtime.

JVM makes a java.lang.Classtype instance for all the types which is a runtime representation. In the code snippet above I took the reference of a Classobject of java.net.URL. java.net.URLclass has six constructors. I used the constructor which takes a string argument. Then took a reference of the method which we want to call. Then made a new instance with the help of a method provided by java reflection. At the end invoked it and printed our desired result. This obviously looks complex but it demonstrates how the reflection works. We are making decisions at the runtime which is the key here.

Use Cases:

Let’s take a reference of java.lang.Class object. Which needs to be done always in order work with reflection API.

Class studentClass = student.getClass();

Using this reference we can access different names, fields, methods or constructors. For example:

String name = studentClass.getName();

Here getName()method returns the fully qualified name with package name. In order to get the public fields of this class getFields()method needs to be called which returns an array. If you want to get the private fields then getDeclaredFields()method needs to be called. Here is an example:

Fields[] fields = studentClass.getDeclaredFields();
for(Field field : fields) {
  System.out.println(field.getName());
}

Like the above examples if you want to know the package of the class then use getPackage()method. For getting the methods use getMethods(). Similarly getConstructors(), getAnnotations(), getInterfaces(), getSuperclass()methods are also available. I guess you got the idea.

 

Calling private methods

You may also call a private method of a class using reflection API. Let’s see an example:

class StudentService {
  private void doSomethingPrivate(String args) {
    System.out.println("argument: " + args);
  }
}

Here is a private method in StudentServiceclass. You will not have any access directly to this method. Now let’s see another code snippet:

public class ExampleAccessingPrivateMethod {
  public static void main(String[] args) {
    try {
      StudentService studentService = new StudentService();
      Class<StudentService> studentServiceClass = 
        StudentService.class;

      Method doSomethingPrivate =
        studentServiceClass.getDeclaredMethod(
        "doSomethingPrivate", String.class);
      doSomethingPrivate.setAccessible(true);
      doSomethingPrivate.invoke( studentService,
             "hello students! Let's bunk the class today");
    } catch (IllegalAccessException 
             | InvocationTargetException 
             |  NoSuchMethodException e) {
      e.printStackTrace();
    }
  }
}

Here a studentServiceinstance is made and object is referred. Through this reference the private method which we want to access is also taken reference of. And in order to access that particular private method, getDeclaredMethod()method is called. You can see setAccessible()method is called to set access right to this method and finally it was invoked and passed the parameter we wanted to pass. You can also dynamically load or reload a class. Not getting into that today.

Summary

Reflection has a lot uses. Using this particular feature, database connections or transaction management frameworks and APIs are written. It is used for creating mock objects in unit testing. Dependency injection or AOP (Aspect Oriented Programming) is also done using the reflection API. But let’s be clear on one thing, reflection is not for everything. You need to use it with balance. It is more like Opium. If used properly it will be very useful otherwise it will give you a hard time.

A lot of examples on the internet are actually available on this topic. You can easily search on google and go through those and have deeper understanding. Thanks for going through the blog. Hope it helped you.

You have ideas, We have solutions.

CONTACT US!