反射的概述
什么是Java反射机制
- Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
Java反射机制的作用
- 是用来编写一些通用性较高的代码或者框架的时候使用。
反射的API
反射常用对象的概述
Class
- Class类的实例表示正在运行的Java应用程序中的类和接口。
Constructor
- 关于类的单个构造方法的信息以及对它的访问权限。
Field
- Field提供了有关类或者接口的单个字段的信息,以及对它的动态访问的权限。
Method
- Method提供了关于类或者接口上单独某个方法的信息。
Class类
- Java中java.lang.Class类用于表示一个类的字节码(.class)文件
- 如何得到某个class文件对应的Class对象
//已知类和对象的情况下
类名.class
对象.getClass() //Object类提供
//未知类和对象的情况下
Class.forName("包名.类名")
- Class类代表了某个类的字节码,并提供了加载字节码的方法:forName(“包名.类名”),forName方法用于加载类字节码到内存中,并封装成一个Class对象。如下代码是常用的一种反射示例代码。
//1. 通过类名.class
Class class1 = Person.class;
//2. 通过对象.getClass()的方式
Person person = new Person();
Class class2 = person.getClass();
//3. Class.forName() 这是更常用的方式
try {
Class.forName("io.github.zbw0520.reflect.test.Person");
} catch (Exception e) {
e.printStackTrace();
}
Constructor类
Constructor类的实例对象代表类的一个构造方法
得到某个类所有的构造方法
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到指定的构造方法并调用
Constructor Constructor = Class.forName("java.lang.String").getConstructor(String.class);
String str = (String)Constructor.newInstance("abc");
- Class类的newInstance()方法用来调用类的默认构造方法
String obj = (String)Class.forName("java.lang.String").newInstance();
- 下面为Constructor类使用的具体实例代码
@Test
/**
* 获得无参数构造方法
*/
public void demo1() throws Exception{
Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
Constructor c = class1.getConstructor();
Person person = (Person)c.newInstance(); //相当于Person person = new Person();
person.eat();
}
@Test
/**
* 获得有参数的构造方法
*/
public void demo2() throws Exception{
Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
Constructor c = class1.getConstructor(String.class,String.class);
Person person = (Person)c.newInstance("张三","男");
System.out.println(person.getName()+" "+person.getGender());
}
Field类
Field类代表了某个类中的一个成员变量,并提供动态的访问权限
Field对象的获得
得到所有的成员变量
Field[] fields = c.getFields();//获取所有public属性(包括父类继承) Field[] fields = c.getDeclaredFields(); //取得所有申明的属性
得到指定的成员变量
Field name = c.getField("name"); //传入属性名称 Field name = c.getDeclaredFields("name"); //经常使用这个函数,无论是私有还是公有都可以通过这个函数访问
设置Field变量是否可以访问
field.setAccessible(boolean); //设置私有属性的访问权限是否为真
Field变量值的读取
field.get(obj); //读取数据 field.set(obj,value); //设置数据
Field类使用代码示例
@Test
/**
* 测试公有属性
*/
public void demo1() throws Exception {
//获得Class
Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
//获得属性
Field name = class1.getField("name");
//操作属性
Person p = (Person)class1.newInstance();
name.set(p,"小王");
System.out.println(name.get(p));
}
@Test
/**
* 测试私有属性
*/
public void demo2() throws Exception{
//获得Class
Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
//获得私有属性
Field f = class1.getDeclaredField("gender");
//操作属性
Person p = (Person)class1.newInstance();
//私有属性需要设置可访问权限
f.setAccessible(true);
f.set(p,"女");
System.out.println(f.get(p));
}
Method类
Method类代表某个类中的一个成员方法
Method对象的获得
获得所有方法
getDeclaredMethods() getMethods
获得指定的方法
getDeclaredMethod(String name, Class<?>...parameterTypes) getMethod(String name, Class<?>...parameterTypes)
通过反射执行方法
invoke(Object obj, Object...args)
- Method类使用代码示例
@Test
/**
* 测试公有方法
*/
public void demo1() throws Exception{
Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
//实例化
Person p = (Person)class1.newInstance();
//获得公有方法
Method mt = class1.getMethod("eat");
//执行该方法
mt.invoke(p);
}
@Test
/**
* 测试私有方法
*/
public void demo2() throws Exception{
Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
//实例化
Person p = (Person)class1.newInstance();
//获得私有方法
Method mt = class1.getDeclaredMethod("run");
//指定可访问性为真
mt.setAccessible(true);
//执行方法
mt.invoke(p);
}
@Test
/**
* 测试带参私有方法
*/
public void demo3() throws Exception{
Class class1 = Class.forName("io.github.zbw0520.reflect.test.Person");
//实例化
Person p = (Person)class1.newInstance();
//获得私有方法
Method mt = class1.getDeclaredMethod("greet",String.class);
//指定可访问性为真
mt.setAccessible(true);
//执行方法
mt.invoke(p,"小明");
}