java_反射

2019-04-28 08:23:29来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

反射: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));

    }
}


 

我有一句话想要对你说

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

 

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


原文链接:https://www.cnblogs.com/aihuadung/p/10783492.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:SSM+Maven+MySQL实现简易的挂机修仙页游

下一篇:Navicat:实现两个数据库结构同步和数据库对比