• JAVA-反射


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

    要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

    阅读API的Class类得知,Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的

    下面直接进行演示。

    首先建立2个类

    Person类

    package cn.bruce.reflect;
    
    public class Person {
        public String name;
        public int age;
        private String address;
    
        public Person()
        {
        }
    
        public Person(String name, int age, String address)
        {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        private Person(String name, int age)
        {
            this.name = name;
            this.age = age;
        }
    
        public void eat() {
            System.out.println(name + "想吃大餐!");
        }
    
        private void eat(String name, int age) {
            System.out.println(name + "想吃大餐!" + "因为今年已经" + age + "岁了!");
        }
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";
        }
    
    }

    Student类

    package cn.bruce.reflect;
    
    public class Student {
        public String name;
        public int age;
        private String address;
    
        public Student()
        {
        }
    
        public Student(String name, int age, String address)
        {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        private Student(String name, int age)
        {
            this.name = name;
            this.age = age;
        }
    
        public void study() {
            System.out.println(name + "想要好好学习!");
        }
    
        private void study(String name, int age) {
            System.out.println(name + "想要好好学习!" + "因为今年已经" + age + "岁了!");
        }
        @Override
        public String toString() {
            return "Student [name=" + name + ", age=" + age + ", address=" + address+ "]";
        }
    
    }

    通过反射获取构造、字段、方法

    package cn.bruce.reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            // Class c = Person.class;//这个是直接的
            // 1,获取到Class对象
            Class c = Class.forName("cn.bruce.reflect.Person");// 包名.类名
            Constructor[] con = c.getConstructors();// 出来公有构造器
            for (Constructor constructor : con)
            {
                System.out.println(constructor);
            }
            System.out.println("------------------------------------------");
            Constructor[] con1 = c.getDeclaredConstructors();// 出来所有构造器
            for (Constructor constructor : con1)
            {
                System.out.println(constructor);
            }
            System.out.println("------------------------------------------");
            Field[] field = c.getFields();// 出来公有字段
            for (Field f : field)
            {
                System.out.println(f);
            }
            System.out.println("------------------------------------------");
            Field[] field1 = c.getDeclaredFields();// 出来所有字段
            for (Field f : field1)
            {
                System.out.println(f);
            }
            System.out.println("------------------------------------------");
            Method[] m1 = c.getDeclaredMethods();// 出来所有方法
            for (Method m : m1)
            {
                System.out.println(m);
            }
            System.out.println("---------------------------");
            Method m2 = c.getMethod("eat", null);// 出来公有指定方法
            System.out.println(m2);
            System.out.println("---------------------------");
            Method m3 = c.getDeclaredMethod("eat", String.class, int.class);// 出来私有指定方法
            System.out.println(m3);
        }
    }

    反射并使用各种方法、泛型擦除、通过配置文件进行反射

    package cn.bruce.reflect;
    
    import java.io.FileReader;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Properties;
    
    public class Test1 {
        public static void main(String[] args) throws Exception {
            // 1,获取到Class对象
            Class c = Class.forName("cn.bruce.reflect.Student");
            // 2,获取指定的构造方法
            // public Student()//空参
            // Constructor con = c.getConstructor(null);
            // public Student(String name, int age, String address)
            Constructor con = c.getConstructor(String.class, int.class, String.class);
            // 3,通过构造方法类中Constructor的方法,创建对象
            // Object obj = con.newInstance(null);//空参
            Object obj = con.newInstance("小明", 22, "哈尔滨");
            // 显示
            System.out.println(obj);
            // 4,获取私有构造方法
            Constructor con1 = c.getDeclaredConstructor(String.class, int.class);
            // 5,暴力反射
            con1.setAccessible(true);// 取消 Java 语言访问检查
            Object obj1 = con1.newInstance("小明", 22);
            System.out.println(obj1);
            // 6,获取指定的方法
            Method m1 = c.getMethod("study", null);// 公有无参方法
            Method m2 = c.getDeclaredMethod("study", String.class, int.class);// 私有
            // 7,执行找到的方法
            m1.invoke(obj);
            m2.setAccessible(true);// M2需要暴力反射
            Object obj_m2 = m2.invoke(obj1, "小米", 99);
            // 以下测试泛型擦除
            ArrayList<Integer> list = new ArrayList<Integer>();
            list.add(999);
            // list.add("小米");出错
            // 1、获取ArrayList的class对象
            Class c_arr = Class.forName("java.util.ArrayList");
            // 2、获取方法
            Method m_arr = c_arr.getMethod("add", Object.class);
            // 3、调用方法
            m_arr.invoke(list, "小米");
            m_arr.invoke(list, "小毛");
            System.out.println(list);
            // 以下演示配置文件实现反射功能
            /*
             * 调用哪种方法不知道,类也不清楚,通过配置文件实现 运行类名与方法名,以键值对的形式,写在文本中 运行哪个类,读取配置文件即可 实现步骤
             * 1、准备配置文件,键值对,IO流读取配置文件reader 2、文件中的键值对存储至集合Properties,集合保存键值对:类名及方法名
             * 3、反射指定的class文件对象,获取方法 运行方法
             */
            // IO流读取
            FileReader fr = new FileReader("config.properties");
            // 创建集合对象
            Properties p = new Properties();
            // 调用集合方法,传递流对象
            p.load(fr);
            fr.close();
            // 通过键获取值
            String classname = p.getProperty("classname");
            String method = p.getProperty("method");
            // 反射获取指定类的文件对象
            Class c_pro = Class.forName(classname);
            // 可以传一下name
    //        Constructor con_pro = c_pro.getConstructor(String.class, int.class, String.class);
    //        Object obj_pro = con_pro.newInstance("笑笑", 33, "杭州");// 创建对象
            Object obj_pro = c_pro.newInstance();
            Method m_pro = c_pro.getMethod(method, null);
            m_pro.invoke(obj_pro, null);
        }
    }

     

  • 相关阅读:
    03 Linux下运行Django项目
    02 Linux常用基本命令(二)
    01 Linux常用基本命令(一)
    08 基本数据结构
    07 Deque的应用案例-回文检查
    给select增加placeholder技巧
    易经中人生的六大阶段 :潜、现、惕、跃、飞、亢 你在第几个阶段?
    java 实现傅立叶变换算法 及复数的运算
    java 正则表达式 复习
    关于mysql varchar(N)
  • 原文地址:https://www.cnblogs.com/BruceKing/p/13819190.html
Copyright © 2020-2023  润新知