Java之反射机制
一、简介
反射由Class类对象开始,从Class对象中,可以获取到有关该类的全部成员的完整列表;可以找出该类的所有类型以及该类实现的接口和扩展的类;可以发现关于类自身的信息,如:修饰符(public、abstract、final等)或者该类所在的包。反射有时也被称为内省,这两个词汇都隐喻了“让类型自我审视并提供自身的描述信息”。这种内省能力也筑就了动态创建和操作对象的第一步。
反射机制能够实现在运行时对类进行加载,增加程序的灵活性,但不恰当的使用反射机制,也会严重影响系统的性能。
反射机制提供的功能主要有:
- 得到一个对象所属的类;
- 获取一个类中的所有成员变量和方法;
- 在运行时创建对象;
- 在运行时调用对象的方法;
二、实现反射的方法
2.1、获取Class的三种方式
- 通过Class.forName(“全类名”);
- 类名.class;
- 对象名称.getClass();
2.2、操作实例:
package com.mengyb.test.dao;
public class Base {
private String address;
public void baseTest1() {
System.out.println("Base----Test1");
}
}
package com.mengyb.test.dao;
public class User extends Base{
private int id;
public String username;
public Integer age;
private String password;
public User() {
}
public User(String username, Integer age) {
this.username = username;
this.age = age;
}
public void test1() {
System.out.println("test1----");
}
private void privateTest() {
System.out.println("privateTest----");
}
public void insert(String username, Integer age) {
System.out.println("username=" + username + "----------age=" + age);
}
}
2.3、动态创建类对象
package com.mengyb.test.demotest;
import com.mengyb.test.dao.User;
public class DemoTest1 {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
System.out.println("--------使用全类名进行获取Bean----------------------");
Class<?> clazz = Class.forName("com.mengyb.test.dao.User"); //动态加载类。
//在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。
User newInstance = (User)clazz.newInstance();
newInstance.test1();
System.out.println("-----------使用对象名称获取Bean-------------------");
User user = new User();
Class<? extends User> aClass = user.getClass(); //动态加载类。
//在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。
User user1 = aClass.newInstance();
user1.test1();
System.out.println("-----------使用类名获取Bean-------------------");
Class clazz2 = User.class; //动态加载类。
//在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。
User user3 = (User)clazz2.newInstance();
user3.test1();
}
}
2.4、对类进行操作
2.4.1、获取类中的属性信息
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.mengyb.test.dao.User");
System.out.println("-------------------获取全类名----------------");
// 获取完整的类名
String clazzName = clazz.getName();
System.out.println("全类名----" + clazzName);
System.out.println("-------------------获取类名----------------");
// 获取类名
String clazzSimpleName = clazz.getSimpleName();
System.out.println("类名----" + clazzSimpleName);
System.out.println("-------------------获取类中所有的public修饰的Field----------------");
//获取类中所有的public修饰的Field
Field[] clazzFields = clazz.getFields();
for (Field field: clazzFields) {
System.out.println("field---" + field);
}
System.out.println("-------------------获取所有Field----------------");
// 获取所有Field
Field[] clazzDeclaredFields = clazz.getDeclaredFields();
for (Field item: clazzDeclaredFields) {
System.out.println("DeclaredFields----" + item);
// 获取Field类型
Class<?> itemType = item.getType();
// 获取Field名称
String itemName = item.getName();
System.out.println("Field---type---" + itemType + "---------FieldName-----" + itemName);
}
}
打印结果
2.4.2、对User对象中的属性进行赋值
public static void main(String[] args) throws Exception {
User user = new User();
user.age = 12;
Class<?> clazz = Class.forName("com.mengyb.test.dao.User");
// newInstance就是一个User对象,底层调用无参构造方法
Object newInstance = clazz.newInstance();
// 获取User中的age属性
Field ageField = clazz.getDeclaredField("age");
// 为age属性赋值
ageField.set(newInstance, user.age);
// 读取age的值
Object ageValue = ageField.get(newInstance);
System.out.println("age属性值-----" + ageValue);
// 访问私有属性
Field idField = clazz.getDeclaredField("id");
// 打破封装(不安全) 默认是false
idField.setAccessible(true);
idField.set(newInstance, 100);
Object idValue = idField.get(newInstance);
System.out.println("id私有属性的值-----" + idValue);
}
为User对象属性赋值及取值的操作
2.4.3、对Method的操作
public static void main(String[] args) {
Class clazz = User.class;
// 获取User中的所有的方法
Method[] clazzDeclaredMethods = clazz.getDeclaredMethods();
// 遍历User中的所有方法
for (Method method: clazzDeclaredMethods) {
System.out.println("-----------------------start-------------");
System.out.println("method-----" + method);
// 获取方法的修饰符
int methodModifiers = method.getModifiers();
System.out.println( "方法的修饰符---" + Modifier.toString(methodModifiers));
// 获取方法的返回值类型
Class<?> methodReturnType = method.getReturnType();
System.out.println("methodReturnType-----" + methodReturnType);
// 获取方法的名称
String methodName = method.getName();
System.out.println("methodName----" + methodName);
// 获取参数类型列表
Class<?>[] methodParameterTypes = method.getParameterTypes();
for (Class item: methodParameterTypes) {
System.out.println("当前参数类型列表-----" + item.getSimpleName());
}
// 获取参数的名称列表
Parameter[] methodParameters = method.getParameters();
for (Parameter item: methodParameters) {
System.out.println("当前参数列表-----" + item.getName());
}
System.out.println("-----------------------end-------------");
}
}
对方法操作的结果展示
2.4.4、通过反射机制对Method进行操作
public static void main(String[] args) throws Exception {
Class clazz = User.class;
// 创建对象
Object newInstance = clazz.newInstance();
// 获取方法
Method insertMethod = clazz.getDeclaredMethod("insert", String.class, Integer.class);
// 调用方法
insertMethod.invoke(newInstance, "zhangsan", 18);
}
结果展示: username=zhangsan----------age=18
2.4.5、通过反射机制操作构造方法
public static void main(String[] args) throws Exception {
//
Class clazz = User.class;
Constructor[] clazzDeclaredConstructors = clazz.getDeclaredConstructors();
// 遍历构造方法
for (Constructor item: clazzDeclaredConstructors) {
System.out.println("构造方法----" + item.getName());
}
Constructor constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
Object newInstance = constructor.newInstance("zhangsan", 18);
// 查看构造是否生效
Field username = clazz.getDeclaredField("username");
System.out.println("username = " + username.get(newInstance));
}
结果展示
2.4.6、通过反射机制查看Bean的父类和接口
public static void main(String[] args) {
Class clazz = User.class;
//
Class clazzSuperclass = clazz.getSuperclass();
System.out.println("获取User的父类" + clazzSuperclass);
Class[] clazzInterfaces = clazz.getInterfaces();
for (Class item: clazzInterfaces) {
System.out.println("接口---" + item);
}
}
【注】 本章为对反射机制的基本运用,如无法满足需求请查看API文档