1.反射基本概念:
01.定义:
反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性!
02.作用:
001.在运行期间获取类的修饰符,包名,类名,实现的接口,继承的父类。
002.在运行期间获取类的所有属性名,修饰符,属性类型。
003.在运行期间获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型。
004.在运行期间加载类的方法。
03.java反射API常用的类
001.java.lang.Class
002.java.lang.reflect.Method
003.java.lang.Constructor
004.java.lang.Filed
005.java.lang.Modifier
2.例子
01.使用java反射获取类的信息
001.父类代码
package cn.pb.bean; /** * 父类 * * @author Administrator * */ public class FatherTest { private String teststr = "测试用"; public String getTeststr() { return teststr; } public void setTeststr(String teststr) { this.teststr = teststr; } }
002.子类代码
package cn.pb.bean; /** * 测试类 人类 继承了父类 */ import java.io.Serializable; public class Person extends FatherTest implements Serializable { private int id; private String name; private String address; private String message; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Person() { super(); } public Person(int id, String name, String address, String message) { super(); this.id = id; this.name = name; this.address = address; this.message = message; } }
003.测试类代码:
package cn.pb.test; /** * 测试类 通过反射获取类的信息 * * @author Administrator * */ public class GetClassInfo { public void test(String className) throws Exception { // 获取Person类对象 传递的className为类的全类名 Class clazz = Class.forName(className); // 获取类在的包名 clazz.getSimpleName():获取类名 Package pkg = clazz.getPackage(); System.out.println(clazz.getSimpleName() + "定义在" + pkg.getName() + "包中!"); System.out.println("*********************"); // 获取此对象所表示的实体(类,接口,基本类型或者void)的超类Class // 如果此对象是一个Object类,一个接口,一个基本类型或void,它的超类返回Null // 如果此对象是一个数组类,返回表示Object类的Class对象 Class superClass = clazz.getSuperclass(); System.out.println(clazz.getSimpleName() + "的超类是" + superClass.getName()); System.out.println("*********************"); // 获取Person类所实现的接口 // 如果Person类没有实现任何接口,返回一个长度为0的数组 // 如果Person类是一个基本类型或者是void,那么也返回一个长度为0的数组 Class[] interfaces = clazz.getInterfaces(); System.out.println("所实现的接口有:"); for (Class c : interfaces) { System.out.println(c.getName()); } System.out.println("******************"); } public static void main(String[] args) throws Exception { GetClassInfo getClassInfo = new GetClassInfo(); getClassInfo.test("cn.pb.bean.Person"); } }
02.使用java反射获取类的构造函数的参数列表,并通过构造函数实例化类
001.父类代码
package cn.pb.bean; /** * 父类 * * @author Administrator * */ public class FatherTest { private String teststr = "测试用"; public String getTeststr() { return teststr; } public void setTeststr(String teststr) { this.teststr = teststr; } }
002.子类代码
package cn.pb.bean; /** * 测试类 人类 继承了父类 */ import java.io.Serializable; public class Person extends FatherTest implements Serializable { private int id; private String name; private String address; private String message; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Person() { super(); System.out.println("通过无参构造实例化Person对象"); } public Person(int id, String name, String address, String message) { super(); this.id = id; this.name = name; this.address = address; this.message = message; System.out.println("通过有参构造实例化Person对象"); } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", address=" + address + ", message=" + message + "]"; } }
003.测试代码
package cn.pb.test; import java.lang.reflect.Constructor; /** * 使用java反射获取类的构造函数的参数列表,并通过构造函数实例化类 * * @author Administrator * */ public class GetClassConstructorInfo { /** * 通过反射实例化类的对象 * * @throws Exception */ public void test1() throws Exception { // 参数calssName,为类的全类名 Class clazz = Class.forName("cn.pb.bean.Person"); // 通过clazz.newInstance()方法,获取类的实例 Object obj = clazz.newInstance(); System.out.println("通过反射实例化的对象:" + obj); } /** * 通过反射获取类的构造函数 * * @throws Exception */ public void test2() throws Exception { // 参数calssName,为类的全类名 Class clazz = Class.forName("cn.pb.bean.Person"); // 获取类的构造函数,返回类的所有公共的构造函数 Constructor[] constructors = clazz.getConstructors(); System.out.println(clazz.getSimpleName() + "类的公共的构造函数以及构造函数的参数列表类型:"); for (Constructor constructor : constructors) { System.out.println("构造函数的名称为:" + constructor.getName()); // 获取构造函数的所有参数 Class[] params = constructor.getParameterTypes(); if (params.length == 0) { System.out.println("此构造函数没有参数!"); } else { System.out.println("该构造函数的参数列表为:【"); for (int i = 0; i < params.length; i++) { if (i != 0) { System.out.println(","); } System.out.println(params[i].getName()); } System.out.println("】"); } } // 获取无参构造,如果参数为空,则获取无参构造 Constructor constructor = clazz.getConstructor(); // 通过无参构造方法获取类的实例 Object obj = constructor.newInstance(); System.out.println("通过无参构造实例化的对象为:" + obj); /** * 获取有参构造 这个方法只能获得公共的有参构造 想要获取私有的构造方法 可以使用 * clazz.getDeclaredConstructor(int.class, String.class, String.class, * String.class);方法 */ Constructor constructor2 = clazz.getConstructor(int.class, String.class, String.class, String.class); Object obj2 = constructor2.newInstance(12, "xiix", "hah", "wawa"); System.out.println("通过有参构造实例化的 对象为:" + obj2); } public static void main(String[] args) throws Exception { GetClassConstructorInfo test = new GetClassConstructorInfo(); // test.test1(); test.test2(); } }
03.使用java反射获取类的所有方法的信息,并调用类的setter方法进行属性的赋值
001.父类代码
package cn.pb.bean; /** * 父类 * * @author Administrator * */ public class FatherTest { private String teststr = "测试用"; public String getTeststr() { return teststr; } public void setTeststr(String teststr) { this.teststr = teststr; } }
002.子类代码
package cn.pb.bean; /** * 测试类 人类 继承了父类 */ import java.io.Serializable; public class Person extends FatherTest implements Serializable { private int id; private String name; private String address; private String message; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Person() { super(); System.out.println("通过无参构造实例化Person对象"); } public Person(int id, String name, String address, String message) { super(); this.id = id; this.name = name; this.address = address; this.message = message; System.out.println("通过有参构造实例化Person对象"); } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", address=" + address + ", message=" + message + "]"; } }
003.测试代码
package cn.pb.test; /** * 使用java反射获取类的所有方法的信息,并调用类的setter方法进行属性的赋值 */ import java.lang.reflect.Method; public class GetClassMethodsInfo { /** * 调用类的setter方法进行属性的赋值 * * @param className * 类的全类名 * @param propName * 属性名 * @param propType * 属性类型 * @param propValue * 属性值 * @throws Exception */ public void invokeSetter(String className, String propName, String propType, Object propValue) throws Exception { // 通过反射获取类的实例 Class clazz = Class.forName(className); Object obj = clazz.newInstance(); // 将传过来的属性名 转换成set方法 String methodName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1); // 根据set方法名和参数列表获取set方法 Method method = clazz.getDeclaredMethod(methodName, Class.forName(propType)); // 如果需要可以设置setAccessible方法,设置为可以访问 // method.setAccessible(true); // 调用方法并传参 参数为:方法所属的对象和方法的参数 method.invoke(obj, propValue);// System.out.println("通过set方法给类的属性赋值:" + obj); } /** * 使用java反射获取类的所有方法的信息 */ public void showMethods() throws Exception { Method[] methods; // 获取Person类中的所有的方法,不包括继承的类的方法 // 如果该类或接口没有生命任何方法,或者此Class 对象表示一个基本数据类型,一个数组类或void // 那么返回一个长度为0的数组 methods = Class.forName("cn.pb.bean.Person").getDeclaredMethods(); System.out.println("******展示方法信息********"); for (Method method : methods) { System.out.println("方法名:" + method.getName()); System.out.println("方法返回值类型:" + method.getReturnType().getName()); // 获取方法的参数列表 Class[] params = method.getParameterTypes(); if (params.length == 0) { System.out.println("该方法没有参数!"); } else { System.out.println("该方法的参数列表为:【"); for (int i = 0; i < params.length; i++) { if (i != 0) { System.out.println(","); } System.out.println(params[i].getName()); } System.out.println("】"); } // 获取方法所属的类或接口的class对象 Class declaringClass = method.getDeclaringClass(); System.out.println("方法声明在:" + declaringClass.getName() + "中!"); // 获取方法抛出的异常的类型,即throws子句中声明的异常 Class[] exceptions = method.getExceptionTypes(); if (exceptions.length > 0) { System.out.println("该方法抛出的异常有:【"); for (int i = 0; i < exceptions.length; i++) { if (i != 0) { System.out.println(","); } System.out.println(exceptions[i].getName()); } System.out.println("】"); } System.out.println("***********************"); } } public static void main(String[] args) throws Exception { GetClassMethodsInfo test = new GetClassMethodsInfo(); // test.invokeSetter("cn.pb.bean.Person", "name", "java.lang.String", // "zhangsan"); test.showMethods(); } }
04.使用java反射获取类的所有属性的名称和类型,并为其中一个属性赋值
001.父类代码
package cn.pb.bean; /** * 父类 * * @author Administrator * */ public class FatherTest { private String teststr = "测试用"; public String getTeststr() { return teststr; } public void setTeststr(String teststr) { this.teststr = teststr; } }
002.子类代码
package cn.pb.bean; /** * 测试类 人类 继承了父类 */ import java.io.Serializable; public class Person extends FatherTest implements Serializable { private int id; private String name; private String address; private String message; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Person() { super(); System.out.println("通过无参构造实例化Person对象"); } public Person(int id, String name, String address, String message) { super(); this.id = id; this.name = name; this.address = address; this.message = message; System.out.println("通过有参构造实例化Person对象"); } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", address=" + address + ", message=" + message + "]"; } }
003.测试代码
package cn.pb.test; import java.lang.reflect.Field; /** * 使用java反射获取类的所有属性的名称和类型,并为其中一个属性赋值 * * @author Administrator * */ public class GetClassFieldsInfo { /** * 使用java反射获取类的所有属性的名称和类型 * * @throws Exception */ public void showFields() throws Exception { Field[] fields; // 获取Person类中的所有字段,但不包括继承的字段 // 如果该类或接口不声明任何字段,或者此Class 对象表示一个基本数据类型,一个数组类或void // 那么返回一个长度为0的数组 fields = Class.forName("cn.pb.bean.Person").getDeclaredFields(); // 遍历 System.out.println("**********字段展示***********"); for (Field field : fields) { System.out.println("字段名:" + field.getName()); System.out.println("字段类型:" + field.getType().getName()); System.out.println("********************"); } } /** * 通过使用反射操作person类的字段 使用java反射获取类的对象的实例,并为其中一个属性赋值 */ public void accessField() throws Exception { // 通过反射加载一个Person实例 Class clazz = Class.forName("cn.pb.bean.Person"); Object obj = clazz.newInstance(); // 通过getDeclaredField("address")方法 获取类的指定字段 Field address = clazz.getDeclaredField("address"); // address字段为private,这里已经超出其访问范围,不能直接访问 // 通过setAccessable方法,设定为可以访问 address.setAccessible(true); System.out.println("赋值前的address:" + address.get(obj)); // 为address属性赋值 address.set(obj, "北大青鸟"); System.out.println("赋值之后的address:" + address.get(obj)); } public static void main(String[] args) throws Exception { GetClassFieldsInfo test = new GetClassFieldsInfo(); test.showFields(); test.accessField(); } }