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

    1. 什么反射 (What is reflect)

    1. 当实例化类的时候,jvm都会寻得.class文件,加载进代码区,为它创建一个Class对象(这个对象是jvm自动创建的,每个.class文件只创建一个Class对象)

    2. 通过Class对象获得Constructor Method Field 对象,然后就可以使用.class里面的所有内容

    2.反射的各种操作 (How to use)

    欲用之,必先有对象

    • 获得.class文件的对象

        //方式一:(推荐的方式,优点语法简介,使用灵活)
        Class classFileObj1 = Class.forName(完整的类名);<下面步骤中都有使用>
        //完整的类名 = 包名 + 类名
        
        //方式二:(缺点要导入包,灵活性较低)
        Class classFileObj2 = 类名.class;
        //所有的类都有一个class的静态属性
    
        //方式三:
        类类型 标识符 = new 类类型();
        //这个中规中矩,没啥好说的
    
    • 这里可能有个疑问,为什么是加类名,而不是加.java的文件名:
      • 有这个疑问的原因是不清楚,jvm的解释机制
        • 当还是.java文件的时候可能会在一个文件里面储存多各类
        • jvm在把.java文件解释成字节码文件的时候会为每个class生成一个.class文件
      • 所以就能解释完整的类名 = 包名 + 类名,而不是加.java的文件名
    • 获得类的构造函数

    类类型 标识符 = new 类类型();

    常规的实例化类就是通过new调用类的构造方法

        //第一步获得.class的对象
        Class classFileObj = Class.forName("完整的类名");
    
        //第二步 获得Constructor 有四种方式:
        //方式一:(获得所有public修饰的构造方法)
        Constructor[] consObj1 = classFileObj.getConstructors();
    
        //方式二:(获得所有** 修饰符 **修饰的构造方法)
        Constructor[] consObj2 = classFileObj.getDeclaredConstructors();
    
        //方式三:(通过指定parameter列表获取public修饰的构造方法)
        Constructor consObj3 = classFileObj.getConstructor(Class.. parameter);
    
        //方式四:(通过指定parameter列表获取** 所有修饰符 **修饰的构造方法)
        Constructor consObj4 = classFileObj.getDeclaredConstruct(Class.. parameter);
    
        //第三步:
        //通过获得的构造函数实例化一个一个对象
        Object obj = consObje3.newInstance(parameter); <后面使用了它>
    
        //第四步:
        //使用它 use it
    
    • 获得类的方法

        //方式一:(获得所有public修饰的方法,包括父类的方法)
        Method[] method1 = classFileObj1.getMethods();
    
        //方式二:(获得所有** 标识符 **修饰的方式,不包括父类的方法)
        Method[] method2 = classFileObj1.getDeclaredMethods();
    
        //方式三:(通过指定方法名和parameter列表获取方法)
        Method method3 = classFileObj1.getMethod(methodName,parameter);
    
        //方式四:(通过指定方法名和parameter列表获取** 所有修饰符修饰的方法)
        Method method4 = classFileObj1.getDeclaredMethod(MethodName,parameter);
    
        //使用获得的方法
        method4.invoke(方法所属的对象,方法所需的参数)
    
        //如果是私有方法
        method4.setAccessible(true);//暴力使用
        method4.invoke(方法所属的对象,方法所需的参数)
    
    
    • 获得类的字段

        //方式一:(获得所有public修饰的字段)
        Field[] field1 = classFileObj1.getFields();
    
        //方式二:(获得所有** 标识符 **修饰的Field)
        Field[] field2 = classFileObj1.getDeclaredFields();
    
        //方式三:(通过指定Field名获取方法)
        Field field3 = classFileObj1.getField(FieldName);
    
        //方式四:(通过指定Field名获取** 所有修饰符修饰的字段)
        Field field4 = classFileObj1.getDeclaredField(FieldName);
    
        //使用设置获得的字段
        field4.set(字段所属对象,要设置的值);
    
        //如果是私有字段
        field4.setAccessible(true);//暴力使用
        field4.set(字段所属的对象,要设置的值)
    
    

    3.反射的简单使用

        //创建一个反射要使用的类
        package com.person;
    
        class Person{
    
            //私有Field
            private int age;
            private String name;
            private int weight;
    
            //public Field
            public int height = 170;
    
            //private Constructor
            private Person(){
                this.age = 10;
                this.weight = 20;
            }
    
            //public Constructot
            public Person(String name){
                this();
                this.name = name;
            }
    
            //public Method
            public void getPersonName(){
                System.out.println("我的名字是:"+this.name);
            }
    
            //private Method
            private void privateGetAge(){
                System.out.println("我的年龄是:"+this.age);
            }
    
            //protected Method
            protected void getHeight(){
                 System.out.println("我的身高是"+this.height);
            }
    
    
        }
    
    
        import java.lang.reflect.*;
    
    try{
        //通过完整的类名,获取Class对象
        Class cls = Class.forName("com.person.Person");
    
        //获得其中一个构造方法
        Constructor oneOfCons = cls.getConstructor(String.class);
        //创建对象
        Person obj = (Person)oneOfCons.newInstance("小明");
        
        //获得方法
        Method oneOfMethod = cls.getDeclaredMethod("getPersonName");
        //使用它
        oneOfMethod.invoke(obj,null);
    
        //获得字段
        Field name = cls.getDeclaredField("name");
        //使用它,因为是私有字段所以必须暴力使用
        name.setAccessible(true);
        name.set(obj,"呼啸");
        //查看是否改变
        oneOfMethod.invoke(obj,null);
    
    }catch(Exception e){
        e.printStackTrace();
    }
    
    
        //结果
        我的名字是:小明
        我的名字是:呼啸
    
  • 相关阅读:
    datanode报错Problem connecting to server
    使用命令查看hdfs的状态
    Access denied for user root. Superuser privilege is requ
    ElasticSearch默认的分页参数 size
    SparkStreaming Kafka 维护offset
    【容错篇】Spark Streaming的还原药水——Checkpoint
    251 Android 线性与相对布局简介
    250 Android Studio使用指南 总结
    249 如何解决项目导入产生的中文乱码问题
    248 gradle更新问题
  • 原文地址:https://www.cnblogs.com/fiwen/p/8977404.html
Copyright © 2011-2022 走看看