Java中的反射
反射是一种 API,用于在运行时检查或修改方法、类和接口的行为。 Java.lang.reflect包下提供了反射所需的类,这对于理解反射至关重要。所以我们用视觉辅助来说明这个包,以便更好地理解如下:
- 反射为我们提供了有关对象所属的类的信息,以及可以使用该对象执行的该类的方法。
- 通过反射,我们可以在运行时调用方法,而不管与它们一起使用的访问说明符。
反射可用于获取有关类、构造函数和方法的信息,如下表所示:Class The getClass() method is used to get the name of the class to which an object belongs. Constructors The getConstructors() method is used to get the public constructors of the class to which an object belongs. Methods The getMethods() method is used to get the public methods of the class to which an object belongs.
如果我们知道它的名称和参数类型,我们可以通过反射调用方法。为此,我们使用如下所述的两种方法,然后继续进行如下操作:
- getDeclaredMethod()
- 调用()
方法一: getDeclaredMethod(): 它 创建要调用的方法的对象。
语法:此方法的语法
Class.getDeclaredMethod(name, parametertype)
参数:
- 要创建其对象的方法的名称
- 类对象数组
方法二: invoke():它在运行时调用类的方法我们使用下面的方法。
句法:
Method.invoke(Object, parameter)
Tip: If the method of the class doesn’t accept any parameter then null is passed as an argument.
Note: Through reflection, we can access the private variables and methods of a class with the help of its class object and invoke the method by using the object as discussed above. We use below two methods for this purpose.
方法三: Class.getDeclaredField(FieldName):用于获取私有字段。返回指定字段名称的 Field 类型的对象。
方法四: Field.setAccessible(true): 允许访问该字段,而不考虑与该字段一起使用的访问修饰符。
从反射 API 得出的重要观察结果
- 可扩展性特性:应用程序可以通过使用其完全限定名称创建可扩展性对象的实例来使用外部的、用户定义的类。
- 调试和测试工具:调试器使用反射属性来检查类的私有成员。
- 性能开销:反射操作的性能比非反射操作慢,在性能敏感的应用程序中频繁调用的代码部分应避免使用。
- 内部暴露:反射代码破坏了抽象,因此可能会随着平台的升级而改变行为。
例子
Java
// Java Program to demonstrate the Use of Reflection
// Importing required classes
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// Class 1
// Of Whose object is to be created
class Test {
// creating a private field
private String s;
// Constructor of this class
// Constructor 1
// Public constructor
public Test() { s = "GeeksforGeeks"; }
// Constructor 2
// no arguments
public void method1()
{
System.out.println("The string is " + s);
}
// Constructor 3
// int as argument
public void method2(int n)
{
System.out.println("The number is " + n);
}
// Constructor 4
// Private method
private void method3()
{
System.out.println("Private method invoked");
}
}
// Class 2
// Main class
class GFG {
// Main driver method
public static void main(String args[]) throws Exception
{
// Creating object whose property is to be checked
// Creating an object of class 1 inside main()
// method
Test obj = new Test();
// Creating class object from the object using
// getClass() method
Class cls = obj.getClass();
// Printing the name of class
// using getName() method
System.out.println("The name of class is "
+ cls.getName());
// Getting the constructor of the class through the
// object of the class
Constructor constructor = cls.getConstructor();
// Printing the name of constructor
// using getName() method
System.out.println("The name of constructor is "
+ constructor.getName());
// Display message only
System.out.println(
"The public methods of class are : ");
// Getting methods of the class through the object
// of the class by using getMethods
Method[] methods = cls.getMethods();
// Printing method names
for (Method method : methods)
System.out.println(method.getName());
// Creates object of desired method by
// providing the method name and parameter class as
// arguments to the getDeclaredMethod() method
Method methodcall1
= cls.getDeclaredMethod("method2", int.class);
// Invoking the method at runtime
methodcall1.invoke(obj, 19);
// Creates object of the desired field by
// providing the name of field as argument to the
// getDeclaredField() method
Field field = cls.getDeclaredField("s");
// Allows the object to access the field
// irrespective of the access specifier used with
// the field
field.setAccessible(true);
// Takes object and the new value to be assigned
// to the field as arguments
field.set(obj, "JAVA");
// Creates object of desired method by providing the
// method name as argument to the
// getDeclaredMethod()
Method methodcall2
= cls.getDeclaredMethod("method1");
// Invokes the method at runtime
methodcall2.invoke(obj);
// Creates object of the desired method by providing
// the name of method as argument to the
// getDeclaredMethod() method
Method methodcall3
= cls.getDeclaredMethod("method3");
// Allows the object to access the method
// irrespective of the access specifier used with
// the method
methodcall3.setAccessible(true);
// Invoking the method at runtime
methodcall3.invoke(obj);
}
}
输出: