反射的概念
根据某个对象来获取该对象所对应的类的完整信息。
反射的功能
- 可以判断运行时对象所属的类;
- 可以判断运行时对象所包含的成员变量和方法。
Java 反射机制中的类
java.lang.Class
java.lang.reflect.Constructor
java.lang.reflect.Field
java.lang.reflect.Method
java.lang.reflect.Modifier
类类型
在 Java 中,万物皆对象,Object 类是所有类的父类,所有类的实例化对象都是 Class 类的对象,Class 类的对象称为类类型。
获取一个类的类类型的方法
首先,我们有一个 Person 类,如下:
package reflecttest;
public class Person {
// 定义 private 修饰的成员变量
private String name;
private int age;
// 定义一个无参构造方法
public Person() {
}
// 定义一个 public 修饰的带参数构造方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
// get set 方法
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;
}
// 重写 toString() 方法
@Override
public String toString() {
return name + ", " + age;
}
}
1. 对象.getClass()
任何一个类都继承了 Object 类,因此也继承了 getClass() 方法,通过该类的对象调用 getClass() 方法可以得到该类的类类型。
public class Test01 {
public static void main(String[] args) {
Person p = new Person();
Class c1 = p.getClass();
// 取得类名
System.out.println(c1);
// 取得包名
System.out.println(c1.getName());
}
}
运行结果:
2. 类名.class
每个类中都隐含了一个静态属性 class,通过 类名.class,也可以获得该类的类类型。
public class Test01 {
public static void main(String[] args) {
Class c2 = Person.class;
// 取得类名
System.out.println(c2);
// 取得包名
System.out.println(c2.getName());
}
}
运行结果:
3. Class.forName
通过动态加载类,Class.forName(“类名的全称(包含包名)”),Class.forName 必须抛出异常或对异常进行捕获处理。
public class Test01 {
public static void main(String[] args) {
try {
Class c3 = Class.forName("reflecttest.Person");
// 取得类名
System.out.println(c3);
// 取得包名
System.out.println(c3.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果:
注: 静态加载,在编译时加载的类称为静态加载类;动态加载,在运行时加载的类称为动态加载类。
通过一个类的类类型获取该类的详细信息
获得一个类的类类型后,可以创建该类对象,并且反射出该类中的方法和属性。
1. 通过类类型创建对象
public class Test02 {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Person p1 = new Person();
Class c1 = p1.getClass();
Person p2 = (Person) c1.newInstance();
Class c2 = Person.class;
Person p3 = (Person) c2.newInstance();
Class c3 = Class.forName("reflecttest.Person");
Person p4 = (Person) c3.newInstance();
// 得到类类型所代表的类名的全称,包含包名
System.out.println(c3.getName());
// 得到类类型所代表的类名,不包含类名
System.out.println(c3.getSimpleName());
}
}
运行结果:
注意: 通过类类型创建对象时,该类必须要有无参的构造方法。
2. 通过类类型反射出该类中所有的属性
在 Java 中,万物皆对象,属性也是对象,它是 Feild 类的对象。
方法 | 描述 |
---|---|
getFeilds() | 获得该类的所有公有属性,包括该类从父类中继承的 |
getDeclaredFields() | 获得所有该类自己声明的属性,不论访问权限 |
getField(name) | 根据给定属性名得到公有的属性的类 |
通过类类型反射出该类中所有的方法
在 Java 中,万物皆对象,方法也是对象,它是 Method 类的对象。
方法 | 描述 |
---|---|
getMethods() | 获得该类的所有 public 方法,包括从父类中继承的和从接口实现的方法 |
getDeclaredMethods() | 获得所有该类自己声明的方法,不论访问权限 |
getMethod(Sting name, Class... parameterTypes) | 根据指定方法和参数列表得到相应的公有方法,包括包括从父类中继承的和从接口实现的方法 |
getDeclaredMethod(Sting name, Class... parameterTypes) | 根据指定方法和参数列表得到该类自己的公有方法 |
通过类类型反射出该类的所有构造方法
在 Java 中,万物皆对象,构造方法也是对象,它是 Constructor 类的对象。
方法 | 描述 |
---|---|
getDeclaredConstructors() | 得到该类的全部构造方法,不论访问权限 |
getConstructors() | 得到该类的公有构造方法 |
参考资料: