• Java基础——反射


    一、反射是什么

      反射机制是在运行状态中,

      对于任意一个类,都能够知道这个类的所有属性和方法;
      对于任意一个对象,都能够调用它的任意一个方法和属性;
      这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    二、反射能做什么

    • 在运行时判断任意一个对象所属的类;

    • 在运行时构造任意一个类的对象;

    • 在运行时判断任意一个类所具有的成员变量和方法;

    • 在运行时调用任意一个对象的方法;

    • 生成动态代理

      学习目标:

    理解 Class 类

    理解 Java 的类加载机制

    学会使用 ClassLoader 进行类加载

    理解反射的机制

    掌握 Constructor、Method、Field 类的用法

    理解并掌握动态代理

    三、反射的API(怎么做)

      1.Class类

      在反射操作之前,必须理解的一个概念是Class类

        每一个类都对应有一个.class文件,.class文件被加载到内存后就对应一个运行时类,存放在缓存区。这个运行时类就是一个Class类的实例!

        每一个Class类的对象都对应着一个类的类型信息!

        更过详细的Class的讲解,强烈推荐:http://www.cnblogs.com/bethunebtj/p/4680532.html

      2.获取Class类实例的方式

        类名.class

    Class clazz = Person.class;

        对象.getClass()

    Class clazz = person.getClass();

        Class.forName("路径") 双击类名copy qualitied name获取路径

    Class clazz = Class.forName("com.jiangbei.demo1.Person");

      // 当然,Class是可以添加泛型的

      只要类一加载,Class实例就被创建,你获取或者不获取,它就在那里,不离不弃。

       3.Class类常用方法

     操作的实体类如下:

    package com.test.demo1.Entity;
    
    /**
     * 人类
     * 作者: Administrator
     * 日期: 2017/9/19
     **/
    public class Human {
        private double weight;
    
        public double getWeight() {
            return weight;
        }
    
        public void setWeight(double weight) {
            this.weight = weight;
        }
        public void eat() {
            System.out.println("Human#eat()...");
        }
    }
    package com.test.demo1.Entity;
    
    import java.io.Serializable;
    
    /**
     * 男性类
     * 作者: Administrator
     * 日期: 2017/9/19
     **/
    public class Man extends Human implements Serializable{
        private Integer age;
        private String name;
        public String hobby;
    
        public void show() {
            System.out.println("Man#show()...");
        }
    
        public String play(String type) throws Exception{
            System.out.println("Man#play()"+type);
            return "play"+type;
        }
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    创建运行时类的对象——newInstance()

    @Test
        public void test1() throws Exception {
            String className = "com.jiangbei.demo1.Person";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 创建运行时类的对象(通过无参公有构造器)
            Person p1 = (Person) clazz.newInstance();
        }

    通过反射调用类的完整结构——Field、Method、Constructor、SuperClass、interface、Annotation

                    属性、方法、构造器、父类、接口、注解

      Field

        获取Field——获取单个指定的field与method,参见API

    @Test
        public void test1() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 获取属性,包括父类的(只能是public的)
            Field[] fields1 = clazz.getFields();
            for (Field field : fields1) {
                System.out.println(field);
            }
            // 获取属性,只能获取本身的属性(所有,只要声明了即有)
            Field[] fields2 = clazz.getDeclaredFields();
            for (Field field : fields2) {
                System.out.println(field);
            }
            // 获取指定属性
            Field field = clazz.getDeclaredField("age");
            // System.out.println(field.getType().getName());
    
        }

     

        通过Field获取属性详细信息——当然还可以通过Field的set/get方法对特定对象属性进行读写操作,详见API(java.lang.reflect)

                      私有属性的访问问题需要先设置权限(field.setAccessible(true))

    @Test
        public void test2() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 获取属性,只能获取本身的属性(所有,只要声明了即有)
            Field[] fields2 = clazz.getDeclaredFields();
            for (Field field : fields2) {
                // 获取属性权限修饰符(使用Modifier进行解码)
                int modifiers = field.getModifiers();
                System.out.println(Modifier.toString(modifiers));
                // 获取属性类型(这个类型也是一个Class实例)
                Class type = field.getType();
                System.out.println(type.getName());
                // 获取属性名(简称)
                System.out.println(field.getName());
            }
    
        }

      Method

        获取Method

    @Test
        public void test3() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 获取方法,包括直接父类和间接父类(所有公有的方法)
            Method[] methods = clazz.getMethods();
           /* for (Method method : methods) {
                System.out.println(method);
            }*/
            // 与属性类似,获取运行时类本身的所有方法
            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                System.out.println(declaredMethod);
            }
        }

     

      //列出部分方法

         通过Method获取详细信息——当然还可以通过invoke()进行方法的调用,可以参见API

    @Test
        public void test4() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 与属性类似,获取运行时类本身的所有方法
            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                // 方法注解
                Annotation[] annotations = declaredMethod.getAnnotations();
                // 方法修饰符
                int modifiers = declaredMethod.getModifiers();
                System.out.print(Modifier.toString(modifiers));
                // 方法返回值
                Class returnType = declaredMethod.getReturnType();
                System.out.println(returnType.getName());
                // 方法名
                String name = declaredMethod.getName();
                System.out.print(name);
                // 形参列表(一般关心类型,形参名字不是重点)
                Class[] paraTypes = declaredMethod.getParameterTypes();
                // 抛出异常
                Class[] exceptionTypes = declaredMethod.getExceptionTypes();
                System.out.println();
            }
        }

    Constructor

        获取构造器——可以通过构造器的newInstance()来进行对象的构造

    @Test
        public void test5() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 获取构造器,本身公有的构造器
            Constructor[] constructors = clazz.getConstructors();
            for (Constructor constructor : constructors) {
                System.out.println(constructor.getName());
            }
        }

    Supperclass

        获取运行时父类(获取父类的泛型)

    @Test
        public void test6() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 获取父类
            Class superclass = clazz.getSuperclass();
            System.out.println(superclass.getSimpleName());
            // 获取父类的泛型
            Type genericSuperclass = clazz.getGenericSuperclass();
            ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            System.out.println(((Class)actualTypeArguments[0]).getName());
        }

     Interfaces

        获取实现的所有接口

    @Test
        public void test7() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 获取接口
            Class[] interfaces = clazz.getInterfaces();
            for (Class anInterface : interfaces) {
                System.out.println(anInterface.getName());
            }
        }

    Package

        获取包

    @Test
        public void test7() throws Exception {
            String className = "com.jiangbei.demo1.Entity.Man";
            // 获取Class实例
            Class clazz = Class.forName(className);
            // 获取包
            Package aPackage = clazz.getPackage();
            System.out.println(aPackage.getName());
        }
  • 相关阅读:
    多线程、事件驱动与推荐引擎框架选型
    Protobuf协议应用干货
    集群选举算法实现
    基于OpenSSL的HTTPS通信C++实现
    通过UNIX域套接字传递描述符的应用
    我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
    C++反射机制:可变参数模板实现C++反射
    git多个远程仓库
    设计模式—模板方法的C++实现
    Java中的运算符
  • 原文地址:https://www.cnblogs.com/zhuangwei1015/p/10009992.html
Copyright © 2020-2023  润新知