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

    反射:reflect   成员属性:Field  成员方法:Method 构造方法:Constructor  类:Class

    引用,援引:invoke   新实例:newInstance  Declared:公开

    什么是反射?

    反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的方法,属性,构造方法等成员

    是一种通过class文件对类中所有成员属性,构造方法,成员方法进行操作的方式,无论是什么权限都可以进行操作

    什么是Class对象?

             学习反射主要是操作Class对象,那么什么是Class对象?

             Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。

    Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

    class文件和Class是两个概念

    也就是说,Class也是java语言中的一个类,程序运行时,会将class文件加载到内存并对该类进行解剖,解剖类时会获得很多的数据,有成员变量数据,成员方法数据,构造方法数据等,JVM为了方便管理这些类的数据,内部会为每一个加载到内存的class文件创建一个Class对象,这个Class对象目的就是用来封装解剖得到的所有该类的数据

    操作Class对象即可获取对应类的数据

    创建对象的五种方式:

    1. 直接new对象

    String str=new String(“张三”);

    1. 如果类中有无参构造方法,可以使用该类对应的Class文件直接创建对象(反射)

    Student s=Student.class.newInstance();

    1. 通过类的Class对象获取该类的构造方法,通过构造方法创建对象(反射)

    Class s1=Student.class;

    Constructor c1=c1.getConstructor();

    Student s2=c1.newInstance();

    1. 通过反序列化获取对象
    2. 通过Clone….获取对象(了解)

    反射有什么用,有什么应用的地方?

    1. 一种新的创建对象,操作对象的方式
    2. 可以降低程序的耦合度,降低程序的维护难度

    举例说明:

    通过反射比较常用的获取类对象的方式:

             Class class=Class.forName(“包名.类名”);

               通过类的全限命名(字符串类型)即可创建对象,可以将该字符串以键值对的形式存储到properties文件中,

               如果类名改变,只需要修改properties配置文件即可

               而通过new出来的对象,如果类名发生改变,则需要修改代码

    1. ssh(Spring,Struts,Hibernate)框架底层就使用了大量的反射

    反射怎么使用?

    先总结一下,通过反射可以获取类的构造方法(Constructor),成员属性(Field),成员方法(Method),针对操作公有数据和操作所有权限数据分开来说

    操作公有数据:

                       获取构造方法:如果构造函数有参数在参数列表加上相应参数类型的class属性即可

                                Constructor getConstructor()

                                Constructor[] getConstructors()

                       获取成员属性:需要传入属性名称

                                Field getField(String name);

                                Field[] getFields();

                       获取成员方法:(通过方法名称和参数才能唯一标识一个方法,所以需要传入方法名称和参数)

                                Method getMethod(String methodName,参数…)

    Method[] getMethods()

             操作所有权限的数据

                                在操作公有数据基础上,get后面加上Declared,如果操作构造方法或者成员属性或者成员方法,先用方法对象或者属性对象调用setAccessible并且传入true即可

    代码详解:

      

    package com.ahd.lianxi;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class Demo01 {
        public static void main(String[] args) throws Exception {
            //练习反射
    
            /*
            * 获取Class对象的三种方式
            * 方式一:通过对象调用getClass方法获取
            *
            * 方式二:通过类名的class属相获取
            *
            * 方式三:通过类的权限命名加载Class文件,需要抛出异常(这种方法比较常用)
            * */
            Student s=new Student("zhangsan");
            Class<? extends Student> c1 = s.getClass();
    
            Class<Student> c2 = Student.class;
    
            Class.forName("com.ahd.lianxi.Student");
    
    
            /*
            * 获取Class对象,可以通过该对象获取该对象相应的构造方法,成员属性
            *       ,成员方法,进而进行操作
            * 首先说操作构造方法,创建对象
            *       Constructor<? extends Student> constructorC1 = c1.getConstructor();
            *           该构造方法获取公有的构造方法,传入相应的参数表示获取对应的构造方法,
            *       Constructor<? extends Student> declaredConstructorC1 = c1.getDeclaredConstructor();
            *           该构造方法获取所有权限的构造方法,传入相应的参数表示获取对应的构造方法,比较常用
            *       Constructor<?>[] constructors = c1.getConstructors();
            *              该构造方法获取所有公有的构造方法,比较常用
            *        Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
            *               该构造方法获取所有权限的构造方法,
            *
            *  如果要通过无参构造方法创建对象,可以直接使用Class对象的newInstance方法获取相应对象
            *         Student student1 = c1.newInstance();
             * */
            Constructor<? extends Student> constructorC1 = c1.getConstructor();
            Constructor<? extends Student> constructorC2 = c1.getConstructor(String.class);
            Constructor<? extends Student> declaredConstructorC1 = c1.getDeclaredConstructor();
    
            Constructor<?>[] constructors = c1.getConstructors();
            Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
            //通过Declared获取的属性,方法..,需要先通过属性对象或者方法对象暴力破解一下
            //declaredConstructorC1.setAccessible(true);
            declaredConstructorC1.setAccessible(true);
            //通过迭代器可以遍历所有构造方法,进行相应操作
            //略...
    
            //使用构造方法创建对象
            Student student = constructorC1.newInstance();
            Student student2 = constructorC2.newInstance("赵四");
    
            /*
            * 通过Class对象获取成员属性
            *           Field field1 = c1.getField("username");
            *                   获取公有的指定属性名称的属性对象
            *           Field field2 = c1.getDeclaredField("username");
            *                   获取所有权限的指定属性名称的属性对象
            *           Field[] fields = c1.getFields();
            *                   获取公有的所有属性对象
            *           Field[] declaredFields = c1.getDeclaredFields();
            *                   获取所有权限的所有属性对象
            * */
            Field field1 = c1.getField("username");
            Field field2 = c1.getDeclaredField("username");
            //通过Declared获取的属性,方法..,需要先通过属性对象或者方法对象暴力破解一下
            //field2.setAccessible(true);
            field2.setAccessible(true);
            
            /*
            * 对属性进行操作
            *       get方法获取属性的值: Object get(Object obj)
            *                           返回指定对象上此 Field 表示的字段的值。
            *       set方法为属性赋值:void set(Object obj, Object value)
            *                   将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
            *                   个人理解:obj即该成员属性所属于的对象,value为为该属性赋的值
            * */
            field1.set(student,"lisi");
            System.out.println(field1.get(student));
    
            Field[] fields = c1.getFields();
            Field[] declaredFields = c1.getDeclaredFields();
            
            //通过迭代器可以遍历所有属性,进行相应操作
            //略...
    
            /*
            * 通过Class对象获取成员方法,获取成员方法需要传入方法名称和参数类型(类型是对应的class文件)
            *       ,方法获取后可以指定对象调用成员方法
            *       ,调用成员方法需要指定对象和参数列表(可变参数)
            *       public Method getMethod(String name,
            *                Class<?>... parameterTypes)
            *                获取公有的成员方法
            *       Method declaredMethod = c1.getDeclaredMethod("getUsername");
            *                 获取所有权限的一个成员方法
            *        Method[] methods = c1.getMethods();
            *                 获取所有公有的成员方法
            *        Method[] declaredMethods = c1.getDeclaredMethods();
            *                   获取所有具有所有权限的成员方法
            *
             *
            * */
            Method method = c1.getMethod("getUsername");//调用无参方法,参数可以不写
            Method declaredMethod = c1.getDeclaredMethod("getUsername");
            //通过Declared获取的属性,方法..,需要先通过属性对象或者方法对象暴力破解一下
            //declaredMethod.setAccessible(true);
            declaredMethod.setAccessible(true);
    
            Method[] methods = c1.getMethods();
            Method[] declaredMethods = c1.getDeclaredMethods();
    
            System.out.println("##########################");
            //方法调用
            method.invoke(student);
            System.out.println(method.invoke(student));
    
        }
    }


    我有一句话想要对你说

    地基越牢固,楼才能建的更高

    笔者原创,欢迎大佬指出错误

  • 相关阅读:
    【Android Developers Training】 73. 布局变化的动画
    【Android Developers Training】 72. 缩放一个视图
    【Android Developers Training】 71. 显示翻牌动画
    svn更改地址怎么办
    python学习手册
    failed to bind pixmap to texture
    Ubuntu 12.04安装Google Chrome
    svn update 时总是提示 Password for '默认密钥' GNOME keyring: 输入密码
    重设SVN 的GNOME keyring [(null)] 的密码
    Nginx + uWSGI + web.py 搭建示例
  • 原文地址:https://www.cnblogs.com/aihuadung/p/10783492.html
Copyright © 2011-2022 走看看