Java中的反射机制------框架设计的灵魂

一、了解反射机制

Java中关于反射的类都在java.lang.reflect包。

1. 框架

半成品软件,可以在框架的基础上进行软件开发,简化代码。学习框架并不需要了解反射,但要是自己写一个框架,就需要对反射有一个深入的学习。

2. 反射机制

反射是类的自省,通过反射可以动态获取类中的方法、构造方法、属性等类的内容。也就是说,对于任意一个类或对象,能够动态获取到这个类的所有属性和方法并可以动态调用对象方法的功能称为反射机制。

我们以往编写的代码都是编译期代码,这些代码是提前写好,固定的代码;
反射在运行期执行的代码,使用反射编写的代码中是没有具体定义哪个对象,它会根据需要在运行期自动的创建类的对象并调用相关方法。

3. 反射的好处

(1)可以在程序运行过程中操作对象。
(2) 可以解耦,提高程序的可扩展性。

在进一步学习反射之前,先了解java代码在计算机中经历的3个阶段。

  • Source源代码阶段:.java文件被编译为.class文件
  • Class类对象阶段:.class文件被类加载器ClassLoader加载进内存,封装成一个Class对象。Class对象将原来字节码文件中的成员变量抽取出来封装成Field[],将构造方法抽取出来封装成Constructor[],将成员方法抽取出来封装成Method[]。除了这三个还有别的封装(以上三个最常用),例如将修饰符抽取出来封装为Modifier[]
  • Runtime运行时阶段:使用new关键字创建对象

q

二、Java反射中的基本使用

1. 获取Class对象

有以下三种方式:

  • 通过类名获得该类的字节码文件
 		Class<User> cls2 = User.class;
        System.out.println(cls2);
  • 通过一个类的完整路径来获得字节码文件
		Class cls1 = Class.forName("com.reflect.cn.User");
        System.out.println(cls1);
  • 通过对象获得字节码文件
 		 User user=new User();
        Class cls3 = user.getClass();
        System.out.println(cls3);

同一个字节码文件在程序运行中只会被加载一次,不论通过哪种方式获得Class对象都是同一个。

2. 通过反射操作类中的属性(成员变量)

  • 操作类中的所有成员变量
		//操作类中的所有属性
  	 private static void getFields() {
        //一个类的字节码文件
        Class cls = User.class;
        //获取类中的所有属性
        Field[] fields = cls.getDeclaredFields();
        //循环遍历fields数组,得到每个属性的详细信息
        for (Field field : fields) {
            //获得属性名称
            String name = field.getName();
            //获得属性的类型
            Class type = field.getType();
            //获得属性的修饰符
            int modifiers = field.getModifiers();
            //将修饰符数字转为相应的字符串
            String modifierStr = Modifier.toString(modifiers);
            System.out.println(modifierStr+" "+type+" "+name);

        }

在这里插入图片描述

  • 获得指定的属性,并调用该属性为该属性赋值及获取值
 //获取指定的属性,并调用该属性为该属性赋值并获取属性
    private static void  getField() throws Exception {
        //获得一个类的字节码对象
        Class cls=User.class;
        //获得某一个属性
        Field user_name = cls.getDeclaredField("user_name");
        //创建类的对象,调用无参的构造方法创建对象
        Object obj = cls.newInstance();
        //调用该属性,设置值。第一个参数的值是对象名,第二个参数是属性值
        user_name.set(obj,"小明");

        //获得属性的值
        Object name = user_name.get(obj);
        System.out.println(name);


    }

在这里插入图片描述

还有一种方法是:
获得所有被public修饰的成员变量 Field[] getFields()
获取指定名称的public修饰的成员变量 Field getField(String name)

3. 通过反射操作类中的方法

  • 获得类中所有方法的细节
//使用反射操作所有的方法
    private static void getMethods() {
        //获取类的字节码文件
        Class cls= User.class;
        //获取类中的方法
        Method[] methods = cls.getDeclaredMethods();
        //循环遍历
        for (Method method : methods) {
            //获取方法的名称
            String name = method.getName();
            //获得方法的返回类型
            Class returnType = method.getReturnType();
            //获得方法的修饰符
            int modifiers = method.getModifiers();
            String modStr = Modifier.toString(modifiers);
            //获得参数列表
            Class[] params = method.getParameterTypes();
            
            System.out.println(modStr+" "+returnType+" "+name+" ");
            System.out.println("参数列表为:");
            for (Class param : params) {
                System.out.println(param);
            }
            //获取异常类型
            Class[] exceptionTypes = method.getExceptionTypes();
            System.out.println("异常类型为:");
            for (Class exceptionType : exceptionTypes) {
                System.out.println(exceptionType);
            }

            System.out.println("============================");


        }
    }
  • 根据方法名和参数列表获得一个方法对象,并调用
 //使用反射操作某一方法
    private static void getMethod() throws Exception {
        //获取某个类的字节码文件
        Class cls=User.class;
        //根据方法名和参数获得一个对象
        Method method = cls.getDeclaredMethod("setUser_id", Integer.class);
        //创建对象
        Object obj = cls.newInstance();
        //调用方法,设置userID的值
        method.invoke(obj,12);

        //获取值
        Method getMethod = cls.getDeclaredMethod("getUser_id");
        //调用方法,并返回结果
        Object userID = getMethod.invoke(obj);
        System.out.println(userID);


    }

4. 根据反射操作类中的构造器

  • 获得所有构造器的细节
//通过反射操作类的所有构造器
    private static void getConstructors() {
        //获取类的字节码对象
        Class cls= User.class;
        //获取类中的构造器
        Constructor[] cons = cls.getDeclaredConstructors();
        //循环遍历
        for (Constructor con : cons) {
            //获得构造器的名称
            String name = con.getName();
            //获得构造器的修饰符
            int modifiers = con.getModifiers();
            String moStr = Modifier.toString(modifiers);
            //获得构造器的参数列表
            Class[] params = con.getParameterTypes();
            System.out.println(moStr+" "+name);
            System.out.println("参数列表");
            for (Class param : params) {
                System.out.println(param);
            }

        }
    }
  • 根据参数列表获得指定的构造器,并利用该构造器创建对象
 //通过反射操作类的某一个构造器
    private static void getConstructor() throws Exception{
        //获取类的字节码对象
        Class cls= User.class;
        //使用无参数的构造器创建对象
        Object obj = cls.newInstance();
        //获得带有参数的构造器
        Constructor constructor = cls.getDeclaredConstructor(Integer.class, String.class, String.class);
        //利用获得的构造器来创建对象
        User user = (User)constructor.newInstance(13, "张三", "1234");
        System.out.println(user);


    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值