反射

作者: 咔狼 | 来源:发表于2018-10-20 12:42 被阅读0次

    概念

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

    Class类

    • 区别于class关键字
    • Class类的实例表示正在运行的Java应用程序中的类和接口,JVM中每个类都有该Class对象(括基本数据类型)
    • Class没有公共构造方法,Class对象是在加载类时由虚拟机以及通过调用类加载器中的defineClass方法自动构造的

    反射的使用

    • 一般用一个清单文件记录所有要通过反射加载的类,程序内读取清单文件加载类

    获取Class对象

    1. Object里面提供的方法getClass()
    2. 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
    3. 通过Class类的静态方法forName(String className)(常用)
      Class class1 = Class.forName(className);// 从path内查找class加载,不能指定路径
    4. 通过ClassLoader获取(常用)

    通过反射获取构造方法

    getConstructor(Class<?>... parameterTypes)
    返回一个Constructor对象,它反映此Class对象所表示的类的指定公共构造方法
    getConstructors()
    返回一个包含某些Constructor对象的数组,这些对象反映此Class对象所表示的类的所有公共构造方法

    通过反射获取成员变量

    getField(String name)
    返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段
    getFields()
    返回一个包含某些Field对象的数组,这些对象反映此Class对象所表示的类或接口的所有可访问公共字段

    通过反射获取成员方法

    getMethod(String name, Class<?>... parameterTypes)
    返回一个Method对象,它反映此Class对象所表示的类或接口的指定公共成员方法
    getMethods()
    返回一个包含某些Method对象的数组,这些对象反映此Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共member方法

    拓展实例

    • 从指定路径的class文件获取类(文件名可自定义)
    • 通常是获取清单文件得到路径及包名
    • 实现方法是重写ClassLoader的findClass方法
    • 被调用class必须实现Access接口(一个指定的接口,用于降低耦合性)
    public class FileClassLoader extends ClassLoader {
    
        private File classFile;
    
        public FileClassLoader(File classFile) {
            super();
            this.classFile = classFile;
        }
    
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {
                byte[] classData = loadClassData();
                return defineClass(name, classData, 0, classData.length);// 通过defineClass方法将类的字节加载为类
            } catch (IOException e) {
                throw new ClassNotFoundException();// IO异常则为类找不到
            }
        }
    
        /**
         * 从文件读取类字节
         *
         * @return 类文件的字节数组
         * @throws IOException
         */
        private byte[] loadClassData() throws IOException {
            final int SIZE = 1024;
            byte[] bytes;
    
            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(classFile))) {
                ByteArrayOutputStream outWriter = new ByteArrayOutputStream();
                byte[] buf = new byte[SIZE];
                int len;
                while ((len = bis.read(buf)) != -1) {
                    outWriter.write(buf, 0, len);
                }
                outWriter.flush();
                bytes = outWriter.toByteArray();
            }
    
            return bytes;
        }
    }
    

    接口(被调用的类必须实现这个接口)

    package reflect;
    
    public interface Access {
        public <T> void method1(T parameter1);
        public <T> void method2(T parameter1, T parameter2);
    }
    

    调用方法

    FileClassLoader fileClassLoader = new FileClassLoader(new File("I:\\JAVA_Project\\Test.class"));// 文件名可自定义
    Class<?> acsClass = fileClassLoader.loadClass("reflect.Test");// 包名
    Access acs = (Access) acsClass.newInstance();// 被调用class必须实现Access接口
    acs.method1("测试打印");// 调用方法
    

    相关文章

      网友评论

          本文标题:反射

          本文链接:https://www.haomeiwen.com/subject/jjzpzftx.html