Java反射的基本概念
Java反射(Reflection)是指在运行时通过程序获取类的信息以及动态调用类的方法和构造方法的一种机制。它让Java程序具有了“运行期关注类信息,运行期获取类信息”等特性,可以动态地创建对象、访问成员变量和方法,甚至可以调用 private 的方法。
在Java中,我们通常将一个类看做一个模板,并在运行时创建这个类的实例来使用。但是,在某些情况下,我们需要在运行时获取类的信息,而不是在编译时就确定好这些信息。这就是Java反射机制要解决的问题。
Java反射机制中的核心类是 Class 类。在Java中,每个类都有一个相应的 Class 对象,它可以表示该类的相关信息,例如类的名称、父类、接口、构造方法、普通方法和成员变量等等。通过 Class 类提供的一系列方法,我们可以实现对类对象的查询、创建和调用相关方法的操作。
反射允许对成员变量,成员方法和构造方法的信息进行编程访问.
说白了就是从类里面拿东西,利用反射可以将成员变量获取出来,然后就可以得到这个成员变量的所有信息
我们可以把这些操作分成两类 获取 解抛
获取这里有一个注意点,我们获取不是从java文件当中去获取,而是从Class字节码文件当中去获取的,所以我们首先学习如何获取Class字节码文件的对象
3.获取Class对象的三种方式:
1.Class.forName(“全类名”);
2.类名.class
3.对象.getClass();
那么什么时候用哪一种呢?其实也是有说法的,如果我们想创建一个类的对象,是分三个阶段的,
源代码阶段: 我们要先编写java
文件,然后再把他编译成Class字节码
文件,这个阶段就是源代码阶段
,在源代码阶段我们会用第一种方式
加载阶段: 我们要把Class字节码
文件加载到内存当中,在加载阶段我们会用第二种方式
运行阶段: 这个时候我们可以去创建类的对象
,在运行阶段我们会用第三种方式
如下图:
JavaBean类展示:
package com.bdqn.获取class对象的三种方式;
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
三种方式:
//1.第一种方式
//全类名: 包名+类名
Class clazz1 = Class.forName("com.bdqn.获取class对象的三种方式.Student");
//2.第二种方式
Class clazz2 = Student.class;
//3.第三种方式
Student s = new Student();
Class clazz3 = s.getClass();
我们已经学会了如何获取Class字节码对象,接下来该学习如何获取构造方法,成员变量,成员方法,那么在学之前我需要大家知道一句话:
在java当中有一个思想,叫做万物皆对象,简单来说就是什么东西都可以把它当成一个对象
那么知道了之后我们就可以这样看:
Class字节码文件:Class对象
在Java反射中,Class类代表了一个类型的元数据信息。每个Java类在编译后都会生成对应的Class对象,该对象包含了类的名称、包名、父类、接口、构造函数、属性和方法等元信息。通过Class对象,可以实现动态获取并操作一个类的信息
构造方法:Constructor
在Java反射机制中,Constructor类代表类中的构造函数
成员变量:Field
在Java反射机制中,Field类代表类中的一个属性(成员变量)。通过反射,我们可以动态获取、修改或创建属性
成员方法:Method
在Java反射机制中,Method类代表类中的一个方法。通过反射机制,可以动态获取并调用类中的方法。
3.Java反射的常用方法
1 获取Class对象
获取一个类的 Class 对象有三种方式:
1.1 通过类的class属性
在类加载时,JVM 会为每个类生成一个Class对象,可以通过类的class属性获取这个对象,例如:
Class clazz = String.class;
1.2 通过对象的getClass()方法
在已知对象的情况下,可以通过对象的getClass()方法获取它的 Class 对象,例如:
String str = "Hello World";
Class clazz = str.getClass();
1.3 通过Class.forName()方法
使用Class.forName()方法可以根据类的全限定名动态地获取它的Class对象,例如:
Class clazz = Class.forName("java.lang.String");
2 获取类的构造方法
使用反射机制可以通过 Class 对象获取类的构造方法,并使用构造方法动态地创建类的实例。以下是获取构造方法的代码示例:
Class clazz = Person.class;
Constructor constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
Person person = (Person) constructor.newInstance("Tom", 18);
注意,构造方法需要传递参数时,需要指定参数类型。如上述代码中,第一行获取Person类的Class对象,第二行通过getDeclaredConstructor()方法获取具有两个参数的构造方法(分别为String和Integer类型),第三行通过newInstance()方法创建Person类的实例。
3 获取类的方法
可以通过 Class 对象获取类的所有方法,包括普通方法、静态方法和私有方法等。以下是获取类的方法的代码示例:
Class clazz = Person.class;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
上述代码中,第一行获取Person类的Class对象,第二行使用getMethods()方法获取类中所有方法,第三行遍历输出所有的方法名。
4 获取类的成员变量
可以通过 Class 对象获取类的所有成员变量,包括公有变量、私有变量和常量等。以下是获取类的成员变量的代码示例:
Class clazz = Person.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
上述代码中,第一行获取Person类的Class对象,第二行使用getDeclaredFields()方法获取类中所有成员变量,第三行遍历输出所有成员变量的名称。
5 调用类的方法和成员变量
使用反射机制可以动态地调用类的方法和成员变量。以下是通过反射调用类的方法和成员变量的代码示例:
Class clazz = Person.class;
Person person = new Person("Tom", 18);
Method method = clazz.getMethod("getName");
Object result = method.invoke(person);
System.out.println(result);
下面我们通过一个简单易懂的实例来了解Java反射机制的基本使用方法。假设我们有一个名为"Person"的类,它有两个私有属性:姓名和年龄,以及一个公共的构造方法和一些公共的方法。现在我们可以利用反射机制来获取并操作这个类。
首先,我们需要通过Class类的静态方法forName()来获取Person类的Class对象:
Class<?> personClass = Class.forName("com.example.Person");
然后,我们可以使用Class类提供的各种方法来获取和设置类的属性和方法。比如,我们可以使用getDeclaredFields()方法来获取所有的属性,用getMethod()方法来获取特定的方法:
Field[] fields = personClass.getDeclaredFields();
Method method = personClass.getMethod("setName", String.class);
最后,我们可以通过Class类提供的newInstance()方法来创建对象,并通过Method类提供的invoke()方法来调用对象的方法:
Object personObj = personClass.newInstance();
method.invoke(personObj, "Tom");
通过这个例子,我们可以看到Java反射的使用过程非常简单,而且可以让程序员在运行时动态地获取和操作类的信息。