1.什么是反射
反射,通俗的说,即在程序运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。对于任意一个对象,都能知道这个对象的所有属性和方法。这种动态获取信息及动态调用对象的方法的功能叫做Java的反射机制。
2.反射和类加载过程的区别
以无参构造为例
正常类加载和创建对象过程:
Java源代码-->类编译器编译成.class文件-->类加载器(ClassLoader)将字节码文件加载到JVM的各个区域;
对象创建:
Person per = new Person();
--编译期加载class文件--》查找构造函数Person()-->通过构造函数Person()创建对象。
反射的加载和对象创建过程:
直接解析class文件,得到类的属性和方法;
对象创建:
Class personClass = Class.forName("com.xiaohan.reflect.Person");//通过全路径名获取Class对象
Constructor con = personClass.getConstructor();//获取无参/有参构造函数
Person person = (Person)con.newInstance();//通过构造函数创建对象
3.创建class对象的三种方式
3.1在没有类实例的情况下(类.class)
Class personClass = Person.class;
3.2有实例的情况下(实例.getClass())
Person p = new Person();
Class pclass = p.getClass();
3.3通过类的全路径名(Class.forName("类的全路径名"))
Class personClass = Class.forName("com.xiaohan.reflect.Person");
以上三种方式获得的Class对象是相等的,
4.通过反射方式获取类的属性和方法
4.1创建一个类(Person)
package com.xiaohan.reflect;
/**
* 定义各种类型和访问权限的属性和方法,验证后面是否都可以通过反射的方式获取到所有属性和方法
*/
public class Person {
public String name = "xiaohan";
protected Integer age = 1;
private Byte sex = (byte)1;
Boolean isMarriage = true;
public Person() {
}
public Person(String name, Integer age, Byte sex, Boolean isMarriage) {
this.name = name;
this.age = age;
this.sex = sex;
this.isMarriage = isMarriage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Byte getSex() {
return sex;
}
public void setSex(Byte sex) {
this.sex = sex;
}
public Boolean getMarriage() {
return isMarriage;
}
public void setMarriage(Boolean marriage) {
isMarriage = marriage;
}
}
4.2通过反射的方式获取类中的各个属性和方法
4.2.1通过无参或有参构造创建对象
public static void main(String[] args) throws Exception {
//获取Class对象
Class personClass = Class.forName("com.xiaohan.reflect.Person");
//方式1:通过无参构造函数创建对象
Constructor constructor = personClass.getConstructor();
Person person = (Person)constructor.newInstance();
//方式2:通过有参构造创建对象
Constructor constructor1 = personClass.getConstructor(String.class,Integer.class, Byte.class, Boolean.class);
Person person1 = (Person) constructor1.newInstance("xiaohan",2,(byte)3,false);
}
4.2.2获取属性
公有属性获取
/**
* 获取对象的属性
* getField:只能获取public的,包括从父类继承来的字段
* getDeclaredField:可以获取本类中所有的字段,包括private的;注,这里只能获取到private的字段,并不能访问该private字段的值,
* 除非加上setAccessible(true).
*/
//public修饰的属性
//Field nameFiled = personClass.getField("name");
Field field = personClass.getDeclaredField("name");
String name = String.valueOf(field.get(person));//通过传入实例,获取具体哪一个实例字段的值
String name2 = String.valueOf(field.get(person1));//通过传入实例,获取具体哪一个实例字段的值
System.out.println("person实例:"+name);
System.out.println("person1实例"+name2);
私有属性获取
//获取私有属性
Field filed2 = personClass.getDeclaredField("sex");
filed2.setAccessible(true);
//获取具体实例的属性
Byte sex = (Byte) filed2.get(person);
Byte sex2= (Byte) filed2.get(person1);
System.out.println("私有属性获取person:"+sex);
System.out.println("私有属性获取person1:"+sex2);