제이온

[Java] Reflection Concept and Usage

Created: 2024-04-25

Created: 2024-04-25 22:27

What is Reflection?

Reflection is an API that supports creating instances of the desired class through the Class type object loaded in the heap area, and supports accessing the fields and methods of the instance regardless of the access modifier.



Here, the loaded class means that after the class loader in the JVM has completed loading the class file, a Class type objectcontaining the information of the class is created and stored in the heap area of the memory. Note that this is different from the object created using the new keyword. If you don't understand the Class type object, it's a good idea to check the JDK documentation for the java.lang.class object.


How to use

Before using reflection, you need to get the Class type object loaded in the heap area. There are a total of three methods.


  • Get it with Class.class
  • Get it with Instance.getClass()
  • Get it with Class.forName("Class name")


You can see that the Class type instances obtained using the three methods are all the same. Regardless of which method is used, the hash value is the same, so use it appropriately according to the situation.


Now, through the obtained Class type, you can create an instance of that class and use the instance's fields and methods regardless of the access modifier. Let's create an instance of the class first.


You can dynamically create a Member instance using getConstructor() to obtain the constructor and newInstance().

Finally, let's access and use the instance's fields and methods regardless of the access modifier.

You can see that getDeclaredFileds() can get all the instance variables of the class, get() can return the field value, and set() can modify the field value. The important thing to note here is that when accessing a field with a private access modifier, you must pass true as the argument to setAccessible().


Methods can also be obtained through getDeclaredMethod(). In this case, you must pass the name of the method and the type of the parameter as arguments. Similarly, when accessing a method with a private access modifier, you must set the argument of setAccessible() to true. Finally, you can call the method obtained through the reflection API using the invoke() method.


Advantages and Disadvantages

  • Advantages
    • It has the flexibility to create instances of classes at runtime and access fields and methods regardless of access modifiers to perform the necessary tasks.
  • Disadvantages
    • It undermines encapsulation.
    • Since instances are created at runtime, the type cannot be checked at compile time.
    • Since instances are created at runtime, it is difficult to understand the specific flow of operation.
    • Performance is slower when accessing fields and methods using reflection than simply accessing them. (Not all situations result in slower performance.)


Reasons for use

Through the Reflection API, you can access class information during runtime and manipulate the class as desired. You can even manipulate fields and methods declared with the private access modifier. Since it breaks encapsulation, which is important in object-oriented design, it may seem like a technology that should not be used.


In small-scale console development, developers can fully understand all the objects and dependencies that will be used in the program at compile time. However, in large-scale development such as frameworks, it is difficult to understand numerous objects and dependencies. In this case, using reflection allows you to dynamically create classes and establish dependencies.


For example, looking at Spring's Bean Factory, you can see that if you simply attach annotations such as @Controller, @Service, and @Repository, the Bean Factory automatically creates and manages the classes with those annotations attached. The developer has never told the Bean Factory about the class, but this is possible thanks to reflection. At runtime, if a class with that annotation is searched and found, it is used by creating an instance of that class through reflection, injecting the necessary fields, and storing it in the Bean Factory.


Of course, as mentioned above, it undermines encapsulation, so it's best to use it only when absolutely necessary.


Source

Comments0