聊java反射

走起

反射的概念是由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);
  • 获取构造器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);
        }
    

猜你喜欢

转载自www.cnblogs.com/share-lu/p/9955887.html