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();
    }
    
    
        //结果
        我的名字是:小明
        我的名字是:呼啸
    
  • 相关阅读:
    Jquery日历插件e-calendar升级版
    jquery双击事件(dblclick)时,不触发单击事件(click)
    js实现的点击div区域外隐藏div区域
    IE浏览器new Date()带参返回NaN解决方法
    RequireJs中使用layer的问题
    AngularJs规范
    js调用Angular的方法
    游标cursor
    bigint数据类型
    ANSI_NULLS和QUOTED_IDENTIFIER
  • 原文地址:https://www.cnblogs.com/fiwen/p/8977404.html
Copyright © 2011-2022 走看看