• Java反射机制


    简介

    Java反射是Java被视为动态语言的一个关键性质。
    
    这个机制允许程序在运行时透过Reflection API取得任何一个已知名称的class的内部信息:
        包括其modifiers(诸如public,static等),super(超类)、
        interfaces(接口),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
    
    Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。
    
    
    反射最重要的用途就是开发各种通用框架:
    
        比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean)
    
        为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,
    
        这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。
    

    Reflection API

    Member接口 用来反映一个成员(成员方法,成员变量)或者是构造器的标识信息
    AccessibleObject类 该类是域(field)对象、方法(method)对象、构造函数(constructor)对象的基础类:打开/抑制默认的Java语言访问控制检查
    Array类 该类提供动态地生成和访问JAVA数组的方法。
    Constructor类 提供一个类的构造函数的信息以及访问类的构造函数的接口。
    Field类 提供一个类的域的信息以及访问类的域的接口。
    Method类 提供一个类的方法的信息以及访问类的方法的接口。
    Proxy类 提供动态地生成代理类和类实例的静态方法。

    获取类的Class对象

    实例对象调用getClass:
        Class<?> classType = user.getClass();   //输出:entity.User
    
    运用 .class 语法:
        Class<?> classType = String.class;  //输出:java.lang.String
    
    运用静态方法 Class.forName():
        Class<?> classType = Class.forName("java.lang.Boolean");    //输出:java.lang.Boolean
    
    运用 .TYPE 语法:
        Class<?> classType3 = Boolean.TYPE; //输出:boolean
    
    
    Class.forName 和 ClassLoader 区别
        Class.forName调用Class.forName(className,true,classloader);在loadClass后必须初始化
        ClassLoader调用ClassLoader.loadClass(className,false);在loadClass后不初始化
    

    获取类的Fields

    public Field getField(String name)
        返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段
    
    public Field[] getFields()
        返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
    
    public Field getDeclaredField(String name)
        返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
    
    public Field[] getDeclaredFields()
        返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
    
    
    getFields 返回的是申明为public的属性,包括父类中定义,
    
    getDeclaredFields 返回的是指定类定义的所有定义的属性,不包括父类的。
    

    获取类的Method

    public Method getMethod(String name,Class<?>... parameterTypes)
        返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法(包括父类)
    
    public Method[] getMethods()
        返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口
        (包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
    
    public MethodgetDeclaredMethod(String name,Class<?>... parameterTypes)
        返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
    
    public Method[] getDeclaredMethods()
        返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,
        包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
    

    获取类的Constructor

    public Constructor<T> getConstructor(Class<?>... parameterTypes)
        返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
    
    public Constructor<?>[] getConstructors()
        返回一个 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
    
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
        返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
    
    public Constructor<?>[] getDeclaredConstructors()
        返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
        它们是公共、保护、默认(包)访问和私有构造方法
    

    实例化

    1、调用类的Class对象的newInstance方法,该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败
    
        Class<?> classType = User.class;
    
        Object inst = classType.newInstance();
    
    
    2、调用默认Constructor对象的newInstance方法
    
        Class<?> classType = User.class;
    
        Constructor<?> constructor = classType.getConstructor();
    
        Object inst = constructor.newInstance();
    
     
    3、调用带参数Constructor对象的newInstance方法
    
        Constructor<?> constructor = classType.getDeclaredConstructor(int.class, String.class);
    
        Object inst = constructor.newInstance(1, "123");
    

    调用类的方法

    Class<?> classType = User.class;
    
    Object inst = classType.newInstance();
    
    Method method = classType.getDeclaredMethod("find", String.class);
    
    method.invoke(inst, "ld");
    

    设置/获取类的属性值

    Class<?> classType = User.class;
    
    Object inst = classType.newInstance();
    
    Field name = classType.getField("name");
    
    name.setInt(inst, 100);
    
    int value = name.getInt(inst);
    

    通过反射越过泛型检查

    泛型用在编译期,编译过后泛型擦除(消失掉),所以是可以通过反射越过泛型检查的
    
    /*
     * String泛型的集合,向这个集合中添加一个Integer类型的值
     */
    public class Demo {
        public static void main(String[] args) throws Exception{
            ArrayList<String> strList = new ArrayList<>();
            strList.add("aaa");
            strList.add("bbb");
            
            Class listClass = strList.getClass();
            //获取add()方法
            Method method = listClass.getMethod("add", Object.class);
            //调用add()方法
            method.invoke(strList, 100);
        }
    }
    

    动态创建代理类

    https://www.cnblogs.com/loveer/p/11300416.html

  • 相关阅读:
    localStorage、sessionStorage、Cookie的区别及用法
    使用BottomNavigationView+ViewPager+Fragment的底部导航栏
    使用BottomNavigationView+ViewPager+Fragment的底部导航栏
    使用BottomNavigationView+ViewPager+Fragment的底部导航栏
    使用BottomNavigationView+ViewPager+Fragment的底部导航栏
    MySQL UDF Dynamic Library Exploit in *nix
    MySQL UDF Dynamic Library Exploit in *nix
    MySQL UDF Dynamic Library Exploit in *nix
    区块链隐私保护:MimbleWimble 和 Grin 简介
    去中心化金融项目 Bloqboard FAQ
  • 原文地址:https://www.cnblogs.com/loveer/p/11587056.html
Copyright © 2020-2023  润新知