zoukankan      html  css  js  c++  java
  • 反射 Reflect

    首先先要明确:  
      所有类都是Object的子类!   所有类的对象都是Class的实例! 反射机制: 在程序运行期间,对于任意一个类,都能知道这个类中所有的属性和方法! (私有的也可以) 对于任意一个对象,我们都能够访问这个对象的所有的属性和方法! 这种动态获取类的信息和动态的调用对象的方法或者属性的功能,我们称之为java中的反射! Animal有两个实现类 一个是Dog 一个是Cat Animal animal=new Dog(); //在代码编译期间 我们就确定了animal的值 Animal animal=??;
    //01.代码编译期间 我们不确定了animal的值 静态
    //02.代码运行期间 我们才能确定了animal的值 动态 java虚拟机提供了我们java程序的运行环境! 其中java虚拟机最重要的任务: 就是管理类和对象的生命周期! 类的生命周期: 从我们类开始加载 连接 初始化 这三步开始的! 加载 连接 初始化 这三步 都执行完毕,才算类的初始化完成! 01.加载 :查询并加载我们类的2进制文件(.class文件) 02.连接:包含3个步骤 001.验证:确保需要加载类的正确性 002.准备:为类中的所有静态数据开辟空间,并赋予默认值 003.解析:把类中的 final ReflectDemo this$0(符号引用) 转换成直接引用 03.初始化 :为类中的所有静态数据开辟空间,赋予初始值

      下面先创建一Student类

    package cn.bdqn.bean;
    
    import java.util.Date;
    
    /**
     * 学生对象的实体类
     */
    public class Student {
    
        public int age; // 学生年龄
        protected String name;// 学生姓名
        private Date birthday = new Date();// 学生生日
        char sex; // 学生性别
    
        static {
            System.out.println("这是Student类中的静态代码块");
        }
    
        {
            System.out.println("这是Student类中的普通代码块");
        }
    
        public Student() {
            System.out.println("这是Student类中的无参构造");
        }
    
        /**
         * 私有的方法
         */
        private double getSum(double number) {
            return number + 10;
        }
    
        public Student(int age, String name, Date birthday, char sex) {
            super();
            this.age = age;
            this.name = name;
            this.birthday = birthday;
            this.sex = sex;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public char getSex() {
            return sex;
        }
    
        public void setSex(char sex) {
            this.sex = sex;
        }
    
    }

      创建测试类

    package cn.bdqn.test;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    import org.junit.Test;
    
    import cn.bdqn.bean.Student;
    
    public class ReflectDemo {
    
        /**
         * 全类名(完整限定名)cn.bdqn.test.ReflectDemo
         *  包名+类名
         *  
         * 完整路径  /Reflect/src/cn/bdqn/test/ReflectDemo.java
         * 
         * 
         * 完整限定名 是我们反射的基础!
         * 问题:
         *     01.一个包中可能出现两个相同的类吗??  不能
         *     02.完整限定名就是来确保我们类的唯一性
         *     03.程序怎么获取完整限定名呢?
         */
        @Test
        public void test01() {
            // 三种方式获取我们的完整限定名
            try {
                System.out.println("第一种方式 :Class.forName()===>"
                        + Class.forName("cn.bdqn.bean.Student").getName());
    
                System.out.println("第二种方式 :类名.Class===>" + Student.class.getName());
                System.out.println("第三种方式 :对象名.getClass()===>"
                        + new Student().getClass().getName());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取类的包名  类名 访问修饰符
         */
        @Test
        public void test02() {
            try {
                Class c = Class.forName("cn.bdqn.bean.Student");
                System.out.println("所在的包:" + c.getPackage().getName());
                System.out.println("全类名:" + c.getName());
                System.out.println("简写的类名:" + c.getSimpleName());
    
                // 获取类的修饰符
                int num = c.getModifiers();
                System.out.println(num);
                // 通过Modifier的toString()就可以把int类型转换成对应的修饰符
                System.out.println(Modifier.toString(num));
    
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取类中所有的属性相关内容
         * 
         * 所有的属性,方法,构造方法 都有修饰符!
         * 不同的访问修饰符 访问权限不一样!
         * Class类中给我们提供了两个方案来获取属性,方法,构造方法!
              01.获取所有的
                       getDeclared系列
              02.获取public修饰的 
                       get系列
         */
        @Test
        public void test03() {
            try {
                Class c = Class.forName("cn.bdqn.bean.Student");
                // Field[] fields = c.getFields(); 只是获取public
                Field[] fields = c.getDeclaredFields(); // 获取所有
                for (int i = 0; i < fields.length; i++) {
                    System.out.println(fields[i]);
                }
    
                // 获取所有属性的访问修饰符 default的int值是0 没有对应的字符串类型
                for (int i = 0; i < fields.length; i++) {
                    System.out.println(Modifier.toString(fields[i].getModifiers()));
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 创建对象
         */
        @Test
        public void test04() {
            // Student stu = new Student(); 耦合
            try {
                Class c = Class.forName("cn.bdqn.bean.Student");
                Student stu = (Student) c.newInstance(); // 相对耦合
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 访问对象的私有属性
         */
    
        @Test
        public void test05() {
            try {
                Class c = Class.forName("cn.bdqn.bean.Student");
                Student stu = (Student) c.newInstance();
    
                Field field = c.getDeclaredField("birthday");
                // 打开访问私有属性的开关
                field.setAccessible(true);
                System.out.println(field.get(stu));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 访问对象的私有方法
         */
    
        @Test
        public void test06() {
            try {
                Class c = Class.forName("cn.bdqn.bean.Student");
                Student stu = (Student) c.newInstance();
    
                Method method = c.getDeclaredMethod("getSum", double.class);
                method.setAccessible(true);
                // 执行方法
                double sum = (Double) method.invoke(stu, 50.0);
                System.out.println(sum);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
  • 相关阅读:
    log4j2 标签解析
    7.3
    work-7.2
    爬取豆瓣上某个用户标记的想读的或者读过的图书信息
    python爬虫程序打包为exe程序并在控制台下运行
    爬取任意两个用户在豆瓣上标记的想读的图书信息的交集
    解决c# progressBar更新出现界面假死
    数据库死锁(大神请路过)
    Excel的下载和读取,部分代码(大神请路过)
    大数据缓存:redis
  • 原文地址:https://www.cnblogs.com/binglong180/p/7588189.html
Copyright © 2011-2022 走看看