- Java Reflection
- Reflection of Java Classes
- Example: Java Class Reflection
- Reflecting Fields, Methods, and Constructors
- 1. Reflection of Java Methods
- 2. Reflection of Java Fields
- 3. Reflection of Java Constructor
- Table of Contents
- Полное руководство по Java Reflection API. Рефлексия на примерах
- Java Reflection API
- Ограничения при работе с рефлексией в Java
- Java Reflection: Работа с классами
Java Reflection
In Java, reflection allows us to inspect and manipulate classes, interfaces, constructors, methods, and fields at run time.
There is a class in Java named Class that keeps all the information about objects and classes at runtime. The object of Class can be used to perform reflection.
Reflection of Java Classes
In order to reflect a Java class, we first need to create an object of Class .
And, using the object we can call various methods to get information about methods, fields, and constructors present in a class.
There exists three ways to create objects of Class:
1. Using forName() method
class Dog // create object of Class // to reflect the Dog class Class a = Class.forName("Dog");
Here, the forName() method takes the name of the class to be reflected as its argument.
2. Using getClass() method
// create an object of Dog class Dog d1 = new Dog(); // create an object of Class // to reflect Dog Class b = d1.getClass();
Here, we are using the object of the Dog class to create an object of Class .
3. Using .class extension
// create an object of Class // to reflect the Dog class Class c = Dog.class;
Now that we know how we can create objects of the Class . We can use this object to get information about the corresponding class at runtime.
Example: Java Class Reflection
import java.lang.Class; import java.lang.reflect.*; class Animal < >// put this class in different Dog.java file public class Dog extends Animal < public void display() < System.out.println("I am a dog."); >> // put this in Main.java file class Main < public static void main(String[] args) < try < // create an object of Dog Dog d1 = new Dog(); // create an object of Class // using getClass() Class obj = d1.getClass(); // get name of the class String name = obj.getName(); System.out.println("Name: " + name); // get the access modifier of the class int modifier = obj.getModifiers(); // convert the access modifier to string String mod = Modifier.toString(modifier); System.out.println("Modifier: " + mod); // get the superclass of Dog Class superClass = obj.getSuperclass(); System.out.println("Superclass: " + superClass.getName()); >catch (Exception e) < e.printStackTrace(); >> >
Name: Dog Modifier: public Superclass: Animal
In the above example, we have created a superclass: Animal and a subclass: Dog . Here, we are trying to inspect the class Dog .
Here, we are creating an object obj of Class using the getClass() method. Using the object, we are calling different methods of Class .
- obj.getName() — returns the name of the class
- obj.getModifiers() — returns the access modifier of the class
- obj.getSuperclass() — returns the super class of the class
Note: We are using the Modifier class to convert the integer access modifier to a string.
Reflecting Fields, Methods, and Constructors
The package java.lang.reflect provides classes that can be used for manipulating class members. For example,
- Method class — provides information about methods in a class
- Field class — provides information about fields in a class
- Constructor class — provides information about constructors in a class
1. Reflection of Java Methods
The Method class provides various methods that can be used to get information about the methods present in a class. For example,
import java.lang.Class; import java.lang.reflect.*; class Dog < // methods of the class public void display() < System.out.println("I am a dog."); >private void makeSound() < System.out.println("Bark Bark"); >> class Main < public static void main(String[] args) < try < // create an object of Dog Dog d1 = new Dog(); // create an object of Class // using getClass() Class obj = d1.getClass(); // using object of Class to // get all the declared methods of Dog Method[] methods = obj.getDeclaredMethods(); // create an object of the Method class for (Method m : methods) < // get names of methods System.out.println("Method Name: " + m.getName()); // get the access modifier of methods int modifier = m.getModifiers(); System.out.println("Modifier: " + Modifier.toString(modifier)); // get the return types of method System.out.println("Return Types: " + m.getReturnType()); System.out.println(" "); >> catch (Exception e) < e.printStackTrace(); >> >
Method Name: display Modifier: public Return Types: void Method Name: makeSound Modifier: private Return Types: void
In the above example, we are trying to get information about the methods present in the Dog class. As mentioned earlier, we have first created an object obj of Class using the getClass() method.
Method[] methods = obj.getDeclaredMethod();
Here, the getDeclaredMethod() returns all the methods present inside the class.
Also, we have created an object m of the Method class. Here,
- m.getName() — returns the name of a method
- m.getModifiers() — returns the access modifier of methods in integer form
- m.getReturnType() — returns the return type of methods
The Method class also provides various other methods that can be used to inspect methods at run time. To learn more, visit the Java Method class (official Java documentation).
2. Reflection of Java Fields
Like methods, we can also inspect and modify different fields of a class using the methods of the Field class. For example,
import java.lang.Class; import java.lang.reflect.*; class Dog < public String type; >class Main < public static void main(String[] args) < try < // create an object of Dog Dog d1 = new Dog(); // create an object of Class // using getClass() Class obj = d1.getClass(); // access and set the type field Field field1 = obj.getField("type"); field1.set(d1, "labrador"); // get the value of the field type String typeValue = (String) field1.get(d1); System.out.println("Value: " + typeValue); // get the access modifier of the field type int mod = field1.getModifiers(); // convert the modifier to String form String modifier1 = Modifier.toString(mod); System.out.println("Modifier: " + modifier1); System.out.println(" "); >catch (Exception e) < e.printStackTrace(); >> >
Value: labrador Modifier: public
In the above example, we have created a class named Dog . It includes a public field named type . Notice the statement,
Field field1 = obj.getField("type");
Here, we are accessing the public field of the Dog class and assigning it to the object field1 of the Field class.
We then used various methods of the Field class:
- field1.set() — sets the value of the field
- field1.get() — returns the value of field
- field1.getModifiers() — returns the value of the field in integer form
Similarly, we can also access and modify private fields as well. However, the reflection of private field is little bit different than the public field. For example,
import java.lang.Class; import java.lang.reflect.*; class Dog < private String color; >class Main < public static void main(String[] args) < try < // create an object of Dog Dog d1 = new Dog(); // create an object of Class // using getClass() Class obj = d1.getClass(); // access the private field color Field field1 = obj.getDeclaredField("color"); // allow modification of the private field field1.setAccessible(true); // set the value of color field1.set(d1, "brown"); // get the value of field color String colorValue = (String) field1.get(d1); System.out.println("Value: " + colorValue); // get the access modifier of color int mod2 = field1.getModifiers(); // convert the access modifier to string String modifier2 = Modifier.toString(mod2); System.out.println("Modifier: " + modifier2); >catch (Exception e) < e.printStackTrace(); >> >
Value: brown Modifier: private
In the above example, we have created a class named Dog . The class contains a private field named color . Notice the statement.
Field field1 = obj.getDeclaredField("color"); field1.setAccessible(true);
Here, we are accessing color and assigning it to the object field1 of the Field class. We then used field1 to modify the accessibility of color and allows us to make changes to it.
We then used field1 to perform various operations on the private field color.
To learn more about the different methods of Field , visit Java Field Class (official Java documentation).
3. Reflection of Java Constructor
We can also inspect different constructors of a class using various methods provided by the Constructor class. For example,
import java.lang.Class; import java.lang.reflect.*; class Dog < // public constructor without parameter public Dog() < >// private constructor with a single parameter private Dog(int age) < >> class Main < public static void main(String[] args) < try < // create an object of Dog Dog d1 = new Dog(); // create an object of Class // using getClass() Class obj = d1.getClass(); // get all constructors of Dog Constructor[] constructors = obj.getDeclaredConstructors(); for (Constructor c : constructors) < // get the name of constructors System.out.println("Constructor Name: " + c.getName()); // get the access modifier of constructors // convert it into string form int modifier = c.getModifiers(); String mod = Modifier.toString(modifier); System.out.println("Modifier: " + mod); // get the number of parameters in constructors System.out.println("Parameters: " + c.getParameterCount()); System.out.println(""); >> catch (Exception e) < e.printStackTrace(); >> >
Constructor Name: Dog Modifier: public Parameters: 0 Constructor Name: Dog Modifier: private Parameters: 1
In the above example, we have created a class named Dog . The class includes two constructors.
We are using reflection to find the information about the constructors of the class. Notice the statement,
Constructor[] constructors = obj.getDeclaredConstructor();
Here, the we are accessing all the constructors present in Dog and assigning them to an array constructors of the Constructor type.
We then used object c to get different informations about the constructor.
- c.getName() — returns the name of the constructor
- c.getModifiers() — returns the access modifiers of the constructor in integer form
- c.getParameterCount() — returns the number of parameters present in each constructor
To learn about more methods of the Constructor class, visit Constructor class
Table of Contents
Полное руководство по Java Reflection API. Рефлексия на примерах
В этой статье мы познакомимся со всеми элементами и функциональными возможностями Java Reflection API.
Рефлексия в Java — это механизм, с помощью которого можно вносить изменения и получать информацию о классах, интерфейсах, полях и методах во время выполнения, при этом не зная имен этих классов, методов и полей. Кроме того, Reflection API дает возможность создавать новые экземпляры классов, вызывать методы, а также получать или устанавливать значения полей.
Начинающие Java-программисты часто путают рефлексию с интроспекцией. Интроспекция — проверка кода и возможность видеть типы объектов во время выполнения. Рефлексия дает возможность вносить изменения во время выполнения программы путем использования интроспекции. Здесь важно понимать различие, поскольку некоторые языки поддерживают интроспекцию, но не поддерживают рефлексию, например, C++.
В этом руководстве мы рассмотрим не только базовые, но и более продвинутые возможности Reflection API.
Java Reflection API
Рефлексия — мощная концепция, которая лежит в основе большинства современных Java/Java EE фреймворков и библиотек. Например, для Java классическими примерами являются:
- JUnit – фреймворк для модульного тестирования. Он использует рефлексию для парсинга аннотаций (например, @Test ) для получения описанных программистом тестовых методов и дальнейшего их выполнения.
- Spring – фреймворк для разработки приложений на Java платформе, в основе которого лежит внедрение зависимостей (инверсия управления).
Список можно продолжать бесконечно: от веб-контейнеров до решения задач объектно-реляционного отображения (ORM). Их всех объединяет одно: они используют Java рефлексию, потому что не имеют доступа и представления к определенных пользователем классах, методах, интерфейсах и т.д.
Ограничения при работе с рефлексией в Java
Почему мы не должны использовать рефлексию в обычном программировании, когда уже есть доступ к интерфейсам и классам. Причин несколько:
- Низкая производительность — поскольку рефлексия в Java определяет типы динамически, то она сканирует classpath, чтобы найти класс для загрузки, в результате чего снижается производительность программы.
- Ограничения системы безопасности — рефлексия требует разрешения времени выполнения, которые не могут быть доступны для систем, работающих под управлением менеджера безопасности (Java Security Manager).
- Нарушения безопасностиприложения — с помощью рефлексии мы можем получить доступ к части кода, к которой мы не должны получать доступ. Например, мы можем получить доступ к закрытым полям класса и менять их значения. Это может быть серьезной угрозой безопасности.
- Сложность в поддержке — код, написанный с помощью рефлексии трудно читать и отлаживать, что делает его менее гибким и трудно поддерживаемым.
Java Reflection: Работа с классами
Объект java.lang.Class является точкой входа для всех операций рефлексии. Для каждого типа объекта, JVM создает неизменяемый экземпляр java.lang.Class который предоставляет методы для получения свойств объекта, создания новых объектов, вызова методов.
В этом разделе мы рассмотрим важные методы при работе с java.lang.Class :
- Все типы в Java, включая примитивные типы и массивы имеют связанный с ними java.lang.Class объект. Если мы знаем название класса во время компиляции, то сможем получить объект следующим образом: