浅谈Java反射机制

寵の児 提交于 2020-08-16 06:05:28

Java反射机制

前言:

最近在看SpringBoot,下午看视频的时候,讲解老师在分析源码,其中源码很多地方用到了反射机制,感觉并没有学习太清楚。之前学习JavaSE的时候有些操之过急,没有好好理解反射机制,于是下午又重新复习了一遍反射机制。

创建对象的几种方式

    1. new关键字 + 该类的构造方法;
    1. 反序列化(和序列化相对应,在I/O流中进行数据传输使用较多,这里篇幅有限,请自行百度);
  • 3)java反射机制

反射的概念

  1. 官方解释:在运行过程中,可以动态根据类的地址来获取类的信息(构造方法,成员方法,成员变量),以及动态根据类的信息来创建对象,来调用对象的方法、属性的功能成为反射机制。
  2. 个人见解: 反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作

反射的作用

可以动态获取类的信息,进一步实现需要实现的功能

反射相关的类

  • Class

    • 用来封装每个类的字节码信息,Java 中一旦某个类被加载到内存中,将会把类的信息封装到一个Class对象中。
  • Constructor 构造方法

  • Method 方法

  • Field 属性

Class 对象

使用反射机制来操作,首先我们需要在运行时获取类的Class对象。

Class对象中包含类的信息(一个类的Class对象只有一个,与字节码文件对应)。

获取Class的三种方式:

(1)通过Object中的getClass()

(2)通过类的class属性

(3)通过类的地址(常用的)

package com.homyit.reflect;

public class ClassDemo {
    public static void main(String[] args) {
        /*
         *  使用反射机制来操作,首先我们需要在运行时获取类的Class对象
         *  Class对象中包含类的信息(一个类的Class对象只有一个,与字节码文件对应)
         */
        //获取Class的三种方法
        //(1)通过Object中的getClass()
        User user1 = new User();
        User user2 = new User();
        
        Class c1 = user1.getClass();
        Class c2 = user2.getClass();
        System.out.println(c1 == c2);       //true
        
        //(2)通过类的class属性
        Class c3 = User.class;
        System.out.println(c1 == c3);       //true
        
        //(3)通过类的地址(常用的)
        try {
            Class c4 = Class.forName("com.homyit.reflect.User");
            System.out.println(c1 == c4);   //true
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }   
    }
}

Java 中Field对象

package com.homyit.reflect;

import java.lang.reflect.Field;

public class FieldDemo {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
        //指定类的路径
        String className = "com.homyit.reflect.User";
                
        //获取包含对象信息的Class对象
        Class c = Class.forName(className);
                
        //通过Class获取User对象
        Object obj = c.newInstance();
        
        //获取属性
        Field numf = c.getDeclaredField("num");
        //设置私有权限
        numf.setAccessible(true);
        //给属性赋值
        numf.setInt(obj, 10);
        
        //获取所有的属性
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.getName());
            String name = field.getName();
            String getname = "get" + String.valueOf(name.charAt(0)).toUpperCase()+name.substring(1);
            System.out.println(getname);
        }
    }
}

java中的method

package com.homyit.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodDemo {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        //指定类的路径
        String className = "com.homyit.reflect.User";
        
        //获取包含对象信息的Class对象
        Class c = Class.forName(className);
        
        //通过Class获取User对象
        Object obj = c.newInstance();
        
        //获取指定方法
        Method m = c.getDeclaredMethod("eat", String.class);
        //设置私有权限
        m.setAccessible(true);
        //调用私有方法
        m.invoke(obj, "cat");
        
        //获取所有的方法
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

反射的经典场景(据说面试常问)

这里给出三个我目前见到过的场景

  • JDBC

加载数据库连接驱动,写过JDBC的同学相信都清楚

Class.forName("com.mysql.jdbc.Driver");
  • servlet

用于servlet对象在服务器tomcat中的创建

<servlet-class>com.company.project.servlet.XxxServlet</servlet-class>

初学servlet时经常配置,后面使用经常使用注解方式,其实底层也是反射机制

  • spring IOC(控制反转)

spring项目中万恶的applicationcontext.xml文件,写过的同学深有体会他的配置有多麻烦

<bean id="course1" class="com.homyit.spring5.collectiontype.Course">
        <property name="cname" value="Spring"></property>
</bean>
<bean id="course2" class="com.homyit.spring5.collectiontype.Course">
        <property name="cname" value="SpringBoot"></property>
</bean>
<bean id="course3" class="com.homyit.spring5.collectiontype.Course">
        <property name="cname" value="SpringCloud"></property>
</bean>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!