JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
- Class 类:反射的核心类,可以获取类的属性,方法等信息。
- Field 类:Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。
- Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
- Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法。
Class对象:
- 要想使用反射,首先需要获得待操作的类所对应的Class对象
- Java中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class对象,这个Class对象是由JVM生成的,通过它能够获悉整个类的结构。
获得Class对象的3种方法:
public static void main(String[] args) {
Person p = new Person();
//方式一:调用实例对象的getClass()方法
Class c1 = p.getClass();
//方式二:调用类的 class 属性来获取该类对应的 Class对象
Class c2 = Person.class;
System.out.println(c1 == c2); // true
try {
//方式三:使用Class类中的 forName()静态方法(最安全/性能最好)
Class c3 = Class.forName("fanshe.Person");
System.out.println(c2 == c3); // true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
创建对象的2种方法:
- 使用 Class 对象的
newInstance()
方法来创建该 Class 对象对应类的实例,但是这种方法要求该 Class 对象对应的类有默认的空构造器。 - 先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的
newInstance()
方法来创建 Class 对象对应类的实例,通过这种方法可以选定构造方法创建实例。
public static void main(String[] args) {
try {
Class clazz = Class.forName("fanshe.Student");
//获取父类
Class superclass = clazz.getSuperclass();
System.out.println("父类:" + superclass.getName());
//获取接口
Class[] interfaces = clazz.getInterfaces();
for (Class c : interfaces) {
System.out.println("父接口:" + c.getName());
}
//获取类的公有构造方法
Constructor[] constructors = clazz.getConstructors();
for (Constructor c : constructors) {
System.out.println("构造方法名称:" + c.getName() + " 修饰符为:" + c.getModifiers());
}
System.out.println("-----------------------");
//获取类的所有构造方法
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
//getModifiers()方法,1代表公有,2代表私有
for (Constructor c : declaredConstructors) {
System.out.println("构造方法名称:" + c.getName() + " 修饰符为:" + c.getModifiers());
}
System.out.println("-----------------------");
//通过反射创建对象
try {
//调用Student类公有的无参构造方法
Object obj = clazz.newInstance();
Student stu = (Student) obj;
//调用Student类公有的带两个参数的构造方法
Constructor constructor = clazz.getConstructor(String.class, int.class);
Student stu1 = (Student) constructor.newInstance("xiaoming", 12);
System.out.println(stu1.getName() + "..." + stu1.getAge());
//通过反射调用私有构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
declaredConstructor.setAccessible(true);//解除私有封装
Student stu2 = (Student) declaredConstructor.newInstance("宝安中学");
System.out.println("-----------------------------");
//获取类的所有公有方法(包括其继承类的公用方法,也包括它所实现接口的方法。)
Method[] methods = clazz.getMethods();
for (Method m : methods) {
System.out.println("方法名:" + m.getName() + " 返回值类型:" + m.getReturnType() + " 修饰符:" + m.getModifiers());
}
System.out.println("-----------------------------");
//获取类的所有方法(包含公有,私有,但不包括继承的方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method m : declaredMethods) {
System.out.println("方法名:" + m.getName() + " 返回值类型:" + m.getReturnType() + " 修饰符:" + m.getModifiers());
}
System.out.println("-----------------------------");
//获取类的公有属性
Field[] fields = clazz.getFields();
for (Field f : fields) {
System.out.println("属性名称:" + f.getName() + " 属性类型:" + f.getType() + " 修饰符:" + f.getModifiers());
}
//获取类的所有属性(包含公有,私有,不包括继承的属性)
System.out.println("-----------------------------");
Field[] declaredFields = clazz.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println("属性名称:" + f.getName() + " 属性类型:" + f.getType() + " 修饰符:" + f.getModifiers());
}
System.out.println("-----------------------------");
//反射机制调用指定方法
Constructor c = clazz.getConstructor(); //无参构造
Object ob = c.newInstance(); //创建对象
Method m = clazz.getMethod("info_1", String.class, int.class);
m.invoke(ob, "zhangsan", 12);//第一个参数为实例对象,后面的参数为当前调用方法的实际参数
//调用私有方法
Method m2 = clazz.getDeclaredMethod("info_2",String.class);
m2.setAccessible(true);
m2.invoke(ob,"lucy");
} catch (Exception e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}