基本概念
能够分析类能力的程序成为反射;反射的功能极其强大;可以用它来分析动态运行时的类的信息。
Class类
Class类用于保存一个类的基本信息,例如属性和方法,构造器。下面简单介绍一下获取Class类实例的三种方式:
(1)Object类中的getClass()方法
通过调用Object类中的getClass()方法可以获取该类Class对象,因为Object类是所有类的父类,所以每个子类的实例都可以调用这个方法获取Class类。
Object object = new Object();
Class clazz = object.getClass();
(2)通过Class.forName()即Class类的forName()静态方法获取Class类。使用这种方式需要处理异常,即类找不到异常。
try {
Class clazz = Class.forName("java.lang.Object");
}catch (ClassNotFoundException exception) {
exception.getStackTrace();
}
(3)通过 类.class 这种方式获取Class类
Class clazz = Object.class;
Class类中的基本方法
我们可以通过以上三种方式中的任意一种获取类的Class类,接下来我们简单介绍Class类中的一些信息:
(1)获取Class类中的Field
- getFields()方法:获取本类及其父类中的所有使用public修饰的属性
- getDeclaredFields()方法:获取本类所有的属性
Class clazz = Object.class;
// 获取本类及其父类中所有使用public修饰的属性
Field[] pubFields = clazz.getFields();
for (Field field : pubFields) {
System.out.print(field + ";");
}
// 获取本类所有的属性
Field[] allFields = clazz.getDeclaredFields();
for (Field field : allFields) {
System.out.print(field + ";");
}
(2)获取Class类中的Constructor
- getConstructors()方法:获取本类及其父类中的所有使用public修饰的构造器
- getDeclaredConstructors()方法:获取本类所有的构造器
Class clazz = Object.class;
// 获取本类及其父类中所有使用public修饰的构造器
Constructor[] pubConstructors = clazz.getConstructors();
for (Constructor constructor : pubConstructors) {
System.out.println(constructor.getName() + ";" + constructor.getParameterCount());
}
// 获取本类所有的构造器
Constructor[] allConstructors = clazz.getDeclaredConstructors();
for (Constructor constructor : allConstructors) {
System.out.println(constructor.getName() + ";" + constructor.getParameterCount());
}
(3)获取Class类中的Method
- getMethods()方法:获取本类及其父类中的所有使用public修饰的方法
- getDeclaredMethods()方法:获取本类所有的构造方法
Class clazz = Object.class;
Method[] pubMethods = clazz.getMethods();
for (Method method : pubMethods) {
System.out.println(method.getName() + ";");
}
Method[] allMethods = clazz.getDeclaredMethods();
for (Method method : allMethods) {
System.out.println(method.getName() + ";");
}
(4)通过反射创建类的实例
- newInstance()方法:获取类的实例
- getConstructors(参数类型) / getDeclaredConstructors(参数类型) . newInstance(参数类型的值) :通过类的带参数的构造器获取实例
注意:参数类型指的是 参数的类型 例如 一个String类型的参数和一个int类型的参数 getConstructors(String.class, int.class) 这表示的是该类中有一个参数是String和int类型的构造器,通过反射调用该构造器为:getConstructors(String.class, int.class). newInstance(”a“, 0) ,newInstance()方法中的值代表传参的值。
举例应用
public class ReflectDemo {
public static void main(String[] args) {
// 获取该类的Class
Class clazz = Reflect.class;
try {
// 获取该类的实例
Object object = clazz.getConstructor(String.class, int.class).newInstance("reflect", 23);
// 通过方法名获取指定的方法
Method method = clazz.getMethod("getName");
// 调用该实例的该方法
Object name = method.invoke(object);
System.out.println(name);
// 通过属性名获取指定的属性
Field field = clazz.getDeclaredField("age");
// 因为该属性是使用private修饰符修饰,所以需要设置该属性可访问,否则程序会报错
field.setAccessible(true);
// 调用该实例的该属性
Object age = field.get(object);
System.out.println(age);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Reflect {
private String name;
private int age;
public Reflect() { }
public Reflect(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
补充说明:setAccessible()这个方法是为了解决通过反射访问实例中的使用private修饰符进行修饰的属性,方法或者构造器,只要在获取属性,方法或者构造器之后,调用他们之前,调用setAccessible(true)方法即可正常访问。