爪哇 - 反射

Posted 赵华强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爪哇 - 反射相关的知识,希望对你有一定的参考价值。

简介

反射是爪哇的一种机制,是指在运行时,可以动态获取信息,可以动态调用对象方法,例如类、方法、接口、变量等信息(无需知道类的名字、方法名等)。

与爪哇反射相关的类如下:

类名用途
Class代表类的实体,在运行的爪哇应用程序中表示类和接口
Field代表类的成员变量(成员变量也称为类的属性)
Method代表类的方法
Constructor代表类的构造方法

1. 获取一个将要被反射的类的方法:

1) 使用 .class 可以在编译时知道具体类名后,获取对象

Class studentClass = Student.class;

2) 使用 Class.forName("……") 在运行时获取对象。由于会找不到类,所以要进行异常捕获

try {
    Class studentClass = Class.forName("Student");
} catch(ClassNotFoundException e) {
    e.printStackTrace();
}

3) 使用对象的 getClass() 方法

String s = new String("Hello");
Class sClass = s.getClass();
案例
package com.github.Student
public class Test {
    public static void main (String[] args) {
        Class studentClass = Student.class;
        System.out.println(studentClass.getName());
        System.out.println(studentClass.getSimpleName());
    }
}

/Library/Java/JavaVirtualMachines/jdk-15.0.2.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=49728:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/Code/works/out/production/works com.github.Student
com.github.Student
Student

Process finished with exit code 0

2. 相关类说明

1) Class

2) Field

3) Method

4) Constructor

I. 获取所有构造方法
public class Test {
    public static void main(String[] args) {
        Class studentClass = Student.class;
        Constructor[] constructors = studentClass.getDeclaredConstructors();
    }
}
附:获取所有构造方法以及每个构造方法的参数类型
for(int i = 0; i < constructors.length; i++) {
    System.out.print(Modifier.toString(constructors[i].getModifiers()) + " 构造参数:");
    Class[] classes = constructors[i].getParameterTypes();
    for(int j = 0; j < classes.length; j++) {
        System.out.print("[" + classes[j].getName() + "]");
    }
    System.out.println();
}

/Library/Java/JavaVirtualMachines/jdk-15.0.2.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=52590:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/Code/works/out/production/works com.github.Test
public 构造参数:[java.lang.String][int]

Process finished with exit code 0

II. 获取所有 public 方法

getConstructors() 可以获取以 public 修饰的所有构造方法

public class Test {
    public static void main(String[] args) {
        Class studentClass = Student.class;
        Constructor[] constructors = studentClass.getConstructors();
    }
}
III. 获取特定方法

通过向 getDelaredConstructor(……) 方法传参可以获得有着某些特定参数的方法,要进行异常捕获因为可能找不到指定的方法

Class[] classes = {String.class, int.class};
try {
    Class studentClass = Student.class;
    Constructor constructor = studentClass.getConstructor(classes);
    System.out.print(Modifier.toString(constructor.getModifiers()) + " 构造参数:");
    Class[] parameters = constructor.getParameterTypes();
    for(int j = 0; j < classes.length; j++) {
        System.out.print("[" + classes[j].getName() + "]");
    }
    System.out.println();
} catch(NoSuchMethodException e) {
    e.printStackTrace();
}

/Library/Java/JavaVirtualMachines/jdk-15.0.2.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=53473:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/Code/works/out/production/works com.github.Test
public 构造参数:[java.lang.String][int]

Process finished with exit code 0

3. 实际运用

I. 调用构造方法
Class[] classes = {String.class, int.class};
Class studentClass = Student.class;
Constructor constructor = studentClass.getDeclaredConstructor(classes);
// constructor.newInstance("Asetg", 10);
Student student = (Student) constructor.newInstance("Ynioh", 19);
II. 调用私有构造方法
Class[] classes = {String.class};
Class studentClass = Student.class;
Constructor constructor = studentClass.getDeclaredConstructor(classes);
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("Qwdfk", 19);
III. 调用方法
// 获取无参无返回的 show()
Method method = studentClass.getDeclaredMethod("show");
method.invoke(constructor.newInstance("Asetg", 10));
// 获取有参无返回的 repeat()
Class[] parameters = {String.class};
Method method2 = studentClass.getDeclaredMethod("repeat", parameters);
Object[] objects = {" Salute! "};
method2.invoke(constructor.newInstance("Asetg", 10), objects);

/Library/Java/JavaVirtualMachines/jdk-15.0.2.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=58735:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/Code/works/out/production/works com.github.Test
Student{name=\'Asetg\', age=10}
您刚才说了 Salute! 吗?

Process finished with exit code 0

IV. 获取私有字段,并修改值
Field field = studentClass.getDeclaredField("name");
field.setAccessible(true);
field.set(student, "Zxcvb");
System.out.println(field.get(student).toString());

/Library/Java/JavaVirtualMachines/jdk-15.0.2.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=58823:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/Code/works/out/production/works com.github.Test
Zxcvb

Process finished with exit code 0

以上是关于爪哇 - 反射的主要内容,如果未能解决你的问题,请参考以下文章

如何在调用 AdapterFragment 之前正确填充数组?爪哇

为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?

OpenGL片段着色器不照亮场景

今天来个爪哇去边框的小代码

如何将 if/else if 代码中的整数转换为该代码外部的整数? (爪哇)

抽象可以不用继承吗?爪哇