• 反射机制


    反射机制

    反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息。 简单的来说,就是不通过new,使用类中的属性和方法。

    为什么需要反射机制:

    1 通过new创建对象 是静态加载类,在编译时刻就需要加载所的有的可能使用的类 (通过动态加载类可以解决该问题)

    2 动态加载类是在运行的时刻加载 -------(一般情况下功能性的类使用动态加载类)

    编译时刻加载类是静态加载类
    运行时刻加载类是动态加载类

    反射机制的优缺点:

    优势:运行期类型的判断,动态类加载:提高代码灵活度

    劣势:性能瓶颈,反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多

    反射机制的应用场景:

    1. JDBC 的数据库的连接
    2. Spring 框架的使用

    Class类

    在面向对象的世界里,万事万物皆对象。

    普通的数据类型不是对象,但是Java给我们提供了封装类,类中的静态成员不是对象,他是属于类的,类是对象,他是java.langa.Class类的实例对象

    如何不用new,获取类中的属性和方法?

    三种方式:

    1.

    类名.class

    // 1.类名.class 方式都返回Class
           Class class1= Foot.class;

    2.

    类的实例对象.getClass()

    //创建类的实例对象
    Foot foot = new Foot();
    // 类的实例对象.getClass()
    Class class2 = foot.getClass();

    3.

    Class.forName("类的路径")

    // 3.Class.forName("类的路径");
    Class class3= Class.forName("/ReflesTest/src/cn/reflex/Foot.java"); //包名+类名


     

    创建所需要的Person类

    package cn.reflex.dome;
    
    public class Person {
    //带参构造
       public Person(int age, String name, String sex) {
            this.age = age;
            this.name = name;
            this.sex = sex;
        }
    //无参构造
    public Person() {
        
        }
    
    //共有属性
    public int age;
     public String name;
       
       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;
    }
    
    //私有属性
    private String sex;
    
    public String getSex() {
        return sex;
    }
    
    public void setSex(String sex) {
        this.sex = sex;
    }
       
    }

     

    1.获取类的包名、类名

        /**
         * 获取包名及类名
         */
        public static void Dome1(){
            Class class1=Person.class;  
            System.out.println("类的包名"+class1.getPackage().getName());
            System.out.println("类的类名"+class1.getName());
        }

     

    2.给类的属性赋值

    /**
         * 获取类的信息
         * @throws IllegalAccessException 
         * @throws InstantiationException 
         */
        public static void Dome2() throws InstantiationException, IllegalAccessException{
            Class class1=Person.class;
            Person person=(Person) class1.newInstance();  //创建Class的实例
            person.setSex("");
            person.setName("小黑");
            System.out.println(person.getName()+person.getSex());
        }

     

     

    3.获取类的构造  给构造属性赋值

    /**
         * 获取类的构造函数
         * @throws IllegalAccessException 
         * @throws InstantiationException 
         * @throws InvocationTargetException 
         * @throws IllegalArgumentException 
         */
        public static void Dome3() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
            Class<Person> class1=Person.class;
            //构造          前提条件是类中要有构造  默认构造  无参构造
            Constructor[] constructors = class1.getConstructors();
            //比如在你的类中无参构造在上面[0]   带参构造[1]
            //[0]下标表示类中的第一个构造
            //[0]此代码中带参构造在第一个,在括号中直接的复制
            Person person=(Person)constructors[0].newInstance(18,"小黑","男");
            System.out.println(person.getName()+person.getSex()+person.getAge());
            //[1]表示无参构造
            Person person2 = (Person) constructors[1].newInstance();
            person2.setAge(55);
            System.out.println(person2.getAge());
            
            
        }

     

    4.获取类中的成员变量

        /**
         *  获取类中所有的成员变量
         * */
        private static void Dome4() {
            Class class1=Person.class;
            //成员变量不一定是一个,所有用数组接收
            Field[] fields = class1.getDeclaredFields();
            //循环遍历数组
          for (Field field : fields) {
              //如果类中有私有变量也想获取怎么办,那就加上下面这一句话
            field.setAccessible(true);
            //获取成员变量名称
            System.out.println(field.getName());
            //获取成员变量的数据类型
            System.out.println(field.getType().getName());
        }
        }

     

    4.1    给类中共有属性赋值

     //获取类中的方法及方法中的参数        三个参数分别是   类中的方法名称   方法中的参数
     Method method1 = class2.getDeclaredMethod("print",int.class,int.class); 
      //给方法中的参数赋值 把类的实例对象传进入
     method1.invoke(foot,1,10);
             

    4.2  给类中私有属性赋值

    // 获取类中的方法及方法中的参数  方法名  参数1,参数2
    Method method1 = class2.getDeclaredMethod("add", int.class, int.class);
    // 如果要给私有方法赋值使用setAccessible(true)
    method1.setAccessible(true);
    // 给方法中的参数赋值 把类的实例对象传进入  类的对象实例,参数1,参数2
    method1.invoke(foot, 1, 10);

    5.

    获取单个成员变量

        /**
         * 获取单个成员变量
         * @throws SecurityException 
         * @throws NoSuchFieldException 
         * 
         * */
        public static void Dome5() throws NoSuchFieldException, SecurityException{
            Class class1=Person.class;
            //想要获取成员变量的名称
            Field field = class1.getDeclaredField("age");
            System.out.println(field.getName());
            System.out.println(field.getType().getName());
            
        }

     

     

    6.获取实现的接口名称  、继承的名字、类中的方法

    创建所需的接口、类

    //接口
    
    package cn.reflex.dome;
    
    public interface ISuper {
        public   void fly();
    }
    //类   并继承Person类   实现接口
    package cn.reflex.dome;
    
    public class Super extends Person implements ISuper  {
        private String type;
        
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        
        public void Wear(String cloths) {
            System.out.println("超人有"+cloths);
        }
        @Override
        public void fly() {
           System.out.println("I Can Fly");        
        }
         
    }

    6.1获取类中实现的接口名称

    1     //获取接口
    2         //可以实现多个接口,所有用数组
    3         Class[] interfaces = class1.getInterfaces();
    4         //遍历数组
    5         for (Class<?> class3 : interfaces) {
    6             System.out.println(class3.getName());
    7         }

    6.2获取类继承的父类名称

    //获取父类名称
    //在这里要得到子类中的信息 
            Class<Super> class1=Super.class;  //子类
            Class<?> class2 = class1.getSuperclass();
            System.out.println(class2.getName());

    6.3获取类中的方法

        //获取方法
            //同样方法不是一个,用数组
            Method[] methods = class1.getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                System.out.println(methods[i].getName());
            }

    6.4获取类中的成员

    //获取类中成员
    Field[] fields = class1.getDeclaredFields();
    for (Field field : fields) {
    System.out.println(field.getName());

     

    7.调用类中的方法,这里用的是子类

        /**
         * 调用类中的方法
         * @throws SecurityException 
         * @throws NoSuchMethodException 
         * @throws InstantiationException 
         * @throws InvocationTargetException 
         * @throws IllegalArgumentException 
         * @throws IllegalAccessException 
         * */
        public static void  Dome7() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
            Class<Super> class1=Super.class;
            //1.想要调用的方法名称传过去
            Method method = class1.getMethod("fly");
            //创建类的实例
            method.invoke(class1.newInstance());
            //2.想要调用的方法名称和方法中的参数
            Method method2 = class1.getMethod("Wear",String.class);
            method2.invoke(class1.newInstance(), "蓝白相间");
        }

     执行结果:

     

    8.使用反射操作泛型集合

    比如我们定义一个数组ArrayList<String> list=new ArrayList<String>();    想数组添加的值必须是String类型的,那如果我们想要添加int类型的怎么办?所以就要用到反射。因为

    反射是在编译后执行的
    泛型集合是在编译前限定的

    使用反射可以绕过编译直接添加到集合中

     

        /**
         * 泛型集合
         * @throws SecurityException 
         * @throws NoSuchMethodException 
         * @throws InvocationTargetException 
         * @throws IllegalArgumentException 
         * @throws IllegalAccessException 
         * */
        
        public static void Dome8() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
            //定义集合,向集合添加元素
            ArrayList<String> list=new ArrayList<String>();
            list.add("小花");
            Class<? extends ArrayList> class1 = list.getClass();
                                              //add是自已定义的,可以随便定义
            Method method = class1.getMethod("add",Object.class);
            method.invoke(list, 100);
            System.out.println(list.size());
            
        }

    我们怎么知道是否添加到集合了呢?使用list.size()输出集合长度

     

     

  • 相关阅读:
    go if 判断 完成随机分数的评级
    go for循环
    go 常量2
    go 常量定义和使用
    更新数据库某字段数据为流水号
    BPM设定操作超时
    BPM打印按钮
    BPM链接处理
    项目管理
    公司规划
  • 原文地址:https://www.cnblogs.com/luoxionghenku/p/8810423.html
Copyright © 2020-2023  润新知