走起
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
作用
在运行时判断任意一个对象所属的类,在运行时构造任意一个类的对象,在运行时判断任意一个类所具有的成员变量和方法,在运行时调用任意一个对象的方法,增强了程序的灵活性和可移植性。
Class类API
-
获取Class类对象的三种方式
- 使用静态方法获取(最常见-运行期检测):
Class clz = Class.forName("包名.类名")
; - 使用类名获取(编译器检测):
Class clz = 类名.class
; - 使用对象获取(编译器检测):
Class clz = 对象.class
;
- 使用静态方法获取(最常见-运行期检测):
-
创建类对象Class
- 通过Class对象
newInstance()
方法(类中存在无参构造函数):clz.newInstance();
- 通过Constructor的
newInstance()
方法获取(initargs
: 参数列表):constructor.newInstance(bject ... initargs);
- 通过Class对象
-
获取构造器Constructor
- 获取所有构造器:
Constructor[] c = clz.getConstructors();
- 获取无参及指定参数的构造器(
parameterTypes
:参数):clz.getConstructor(Class<?>... parameterTypes);
- 获取所有构造器:
-
获取属性Field
- 获取本类所有属性:
Field[] f = clz.getDeclaredFields();
- 获取本类指定的属性(
name
: 属性名):Field f = clz.getFields(String name);
- 获得本类、父类、接口的所有public修饰的属性:
Field[] f = clz.getFields();
- 获得本类、父类、接口中指定的public修饰的属性(
name
: 属性名):Field f = clz.getField(String name);
- 获取本类所有属性:
-
获取接口
- 获得该类所实现的所有接口:
Class[] c = cls.getInterfaces();
- 获得该类所实现的所有接口:
-
获取方法Method
- 获取本类所有实现方法:
Method[] m = cls.getDeclaredMethods();
- 获取本类指定的方法(
name
:方法名,parameterTypes
:参数数组):Method m = cls.getMethod(String name, Class<?>... parameterTypes);
- 获取本类、父类中所有public修饰实现方法及接口中的default方法:
Method[] m = cls.getMethods();
- 获取本类、父类中指定的public修饰的方法及接口中的default方法(
name
:方法名,parameterTypes
:参数数组):Method m = cls.getMethod(String name, Class<?>... parameterTypes);
- 获取本类所有实现方法:
Method类API
- 调用方法(
obj
:调用的对象;args
:调用方法参数的数组):method.invoke(Object obj, Object... args)
上代码
-
订单接口
public interface OrderIntf { //测试获取Field的方法使用,getFields()可以获取到本接口中的属性 String price = "1"; //测试获取Method的方法使用,getMethods()不可以获取到本接口中的静态方法 static void staticMethod() { System.out.println("接口中的静态方法"); } //测试获取Method的方法使用,getMethods()可以获取到本接口中的静态方法 default void defaultMethod(){ System.out.println("接口中的默认方法"); } /** * 获取对应用户订单数量 */ Integer getOrderNum(String userId); }
-
订单父类
@Getter @Setter public class OrderFather { //测试子类getFields方法使用,不可以获取到本方法 private String createTime; //测试子类getFields方法使用,可以获取到本方法 public String remark; //测试子类getMethods方法使用,可以获取到本方法 public void testPublic(){ } //测试子类getMethods方法使用,不可以获取到本方法 private void testPrivate(){ } }
-
订单类
@Getter @Setter public class Order extends OrderFather implements OrderIntf { public Order() { super(); } /** * 构造方法 * @param orderNo * @param orderStatus */ public Order(String orderNo, String orderStatus) { this.orderNo = orderNo; OrderStatus = orderStatus; } /** * 订单号 */ private String orderNo; /** * 订单状态 */ private String OrderStatus; /** * 创建人 */ public String createName; @Override public Integer getOrderNum(String userId) { return null; } }
-
反射测试类
public class OrderReflect { public void reflect() throws Exception{ //使用类名获取 Class<Order> orderClass = Order.class; //通过类对象获取 Order order1 = new Order(); Class<?> orderClass1 = order1.getClass(); //通过静态方法获取 Class<?> orderClass2 = Class.forName("com.share..Order"); System.out.println(orderClass == orderClass1); System.out.println(orderClass1 == orderClass2); //获取构造时,需要传入该构造的的参数类型 Class[] classes = new Class[]{String.class, String.class}; //获取类的参数为String和String类型的public构造函数 Constructor constructor = orderClass.getConstructor(classes); Constructor constructor1 = orderClass.getConstructor(); //通过有参构造方法构造一个Order实例 Order order = (Order) constructor.newInstance("O123456", "1"); //通过无参构造方法构造一个实例 Order order2 = (Order) orderClass1.newInstance(); Order order3 = (Order) constructor1.newInstance(); //获得该类所实现的所有接口 Class[] c = orderClass.getInterfaces(); System.out.println(c.length); //获取本类、父类、接口中所有public的属性 Field[] fs = orderClass.getFields(); for (Field f : fs){ System.out.println("getFields:" + f.getName()); } //获取本类所有的属性 Field[] fs1 = orderClass.getDeclaredFields(); for (Field f : fs1){ System.out.println("getDeclaredFields:" + f.getName()); } //获取本类、父类中所有public的方法 Method[] ms = orderClass.getMethods(); for(Method m : ms){ System.out.println("getMethods:" + m.getName()); } //获取本类所有实现方法 Method[] ms1 = orderClass.getDeclaredMethods(); for(Method m : ms1){ System.out.println("getDeclaredMethods:" + m.getName()); } //获取Order中名字为getOrderNo的方法 Method m = orderClass.getMethod("getOrderNo", new Class[]{}); //执行方法实例的getOrderNo方法 String orderNo = (String)m.invoke(order, new Object[]{}); System.out.println("订单号:" + orderNo); }