java文件编译成class文件,ClassLoader加载class文件到JVM中,然后运行,不同的class会有不同的ClassLoader,这个过程叫运行,运行过程中ClassLoader可以通过class动态的获得A类中的属性和方法,动态生成A的对象实例,称为反射机制
反射是在运行期间对于任意被加载到内存的class来动态获取它的属性和方法
(1).class文件加载到内存后会形成一个对象,即Person类加载到内存后形成一个Class类的对象,获得Class对象后就可以获得Person类的属性和方法,即获得其他内容的前提
(2)构造函数加载到内存后会形成一个Constructor类的对象,获得Constructor的对象后可以创建对象的实例
(3)一个属性加载到内存后形成一个Field对象,获得Field对象后可对属性赋值
(4)方法加载到内存后形成一个Method对象,拿到这个Method对象后就可以对方法进行相应的操作
反射第一步先获得class文件对应的Class对象,即获得代表类的字节码文件所对应的Class对象
public class ClassTest {
/**
* 获得class对象
* 1.类名.class
* 2.对象.getClass()
* 3.Class.forName()
*/
public void demo1() throws ClassNotFoundException {
Class class1=Person.class;
Person p=new Person();
Class class2=p.getClass();
//反射通常是在不知道类实例的情况下进行操作的,推荐Class.forName()
Class class3=Class.forName("database.Person");
}
}
getConstructor()里面传递的是一个Class类型的可变参数,获得公有构造
getDeclaredConstructor()获得私有构造
Constructor类的newInstance()方法:使用此Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例
/**
* 获得无参数的构造方法
*/
public void demo1() throws Exception {
//获得类的字节码文件对应的对象
Class class1 = Class.forName("database.Person");
//获得无参构造
Constructor c = class1.getConstructor();
//生成对象,实际返回的是一个通用的Object类型,已知是Person实例,可以用Person来接收
//相当于Person person=new Person();
Person person = (Person) c.newInstance();
}
/**
* 获得有参构造方法
*/
public void demo2() throws Exception {
//获得类的字节码文件对应的对象
Class class1 = Class.forName("database.Person");
//获得有参构造,构造函数中需要传递两个字符串类型的参数
Constructor c = class1.getConstructor(String.class, String.class);
//newInstance()需要传入具体的参数
//相当于Person person=new Person("1","2");
Person person = (Person) c.newInstance("1", "2");
}
getDeclaredFields()可以获得所有声明的属性,更常使用,要获得私有属性时需要设置Field变量是否可以被访问,设置为true,私有属性可以被访问
public class FieldTest {
/**
* 测试公有的属性
*/
public void demo1() throws Exception{
//获得class
Class class1=Class.forName("database.Person");
//获得属性
Field field1= class1.getField("name");
//操作属性 p.name="...";
//Person p=(Person)class1.getConstructor().newInstance();
Person p=(Person)class1.newInstance();
field1.set(p,"1");//p.name=1;
Object obj=field1.get(p);//返回一个Object,因为属性可以是任意类型
}
/**
* 重点是反射私有的属性,私有属性没有get和set方法时
*/
public void demo2() throws Exception{
//获得class
Class class1=Class.forName("database.Person");
//获得属性
Field field1= class1.getDeclaredField("sex");
//操作属性 p.name="...";
//Person p=(Person)class1.getConstructor().newInstance();
Person p=(Person)class1.newInstance();
//私有属性需要设置一个可访问的权限
field1.setAccessible(true);
field1.set(p,"1");//p.name=1;
Object obj=field1.get(p);//返回一个Object,因为属性可以是任意类型
}
}
获得指定的方法需要传入方法名和方法参数
public class MethodTest {
/**
* 测试公有的方法
*/
public void demo1() throws Exception{
Class class1=Class.forName("database.Person");
//实例化
Person p=(Person)class1.newInstance();
//获得公有方法
Method m=class1.getMethod("eat");
//执行该方法
m.invoke(p);//person.eat();
}
/**
* 测试私有的方法
*/
public void demo2() throws Exception{
Class class1=Class.forName("database.Person");
//实例化
Person p=(Person)class1.newInstance();
//获得私有方法
Method m=class1.getDeclaredMethod("run");
//设置私有的属性的访问权限
m.setAccessible(true);
m.invoke(p);
}
/**
* 测试私有的方法带参数和返回值
*/
public void demo3() throws Exception{
Class class1=Class.forName("database.Person");
//实例化
Person p=(Person)class1.newInstance();
//获得私有方法
Method m=class1.getDeclaredMethod("sleep",String.class);
m.setAccessible(true);
//执行
Object obj=m.invoke(p,"1");
}
}