Java - 反射概念

  • 反射概念:"反"是相对于"正"而言的,通常情况下,如果我们想要使用某个类中的方法首先需要知道是哪个类,然后new一个类对象,通过创建的对象去调用相应的方法。而反射机制则是允许在程序运行过程中,根据Class对象或者一个具体的类对象就可以获取整个类的结构信息(构造器、属性、方法等)。
  • 反射作用:可以通过Class对象(字节码对象,.class文件被加载到内存时创建)进行一系列类及其对象所拥有的操作(调用方法、属性赋值等)。
package main.java.per.learning.reflection;

import java.lang.annotation.ElementType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Test;

public class MyReflection {
   
    /**
     * 获取Class对象
     */
    @Test
    public void getClassTest() throws ClassNotFoundException {
        // 1. 使用Class.forName + 全限定类名
        Class c1 = Class.forName("main.java.per.learning.reflection.User");
        // 2. 对象名
        User user = new User();
        Class c2 = user.getClass();
        // 3. 类名
        Class c3 = User.class;
        // 在内存中,一个类仅有一个Class类对象
        // 一个类被加载后,类的结构信息都被封装在Class类对象中
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
    }

    /**
     * 所有的Class类型
     */
    @Test
    public void classTypeTest(){
        Class c1 = Object.class; // 类
        Class c2 = Comparable.class; // 接口
        Class c3 = String[].class; // 一维数组
        Class c4 = int[][].class; // 二维数组
        Class c5 = Override.class; // 注解
        Class c6 = ElementType.class; // 枚举
        Class c7 = Integer.class; // 基本类型(包装)
        Class c8 = void.class; // void
        Class c9 = Class.class; // Class

        System.out.println("c1:" + c1);
        System.out.println("c2:" + c2);
        System.out.println("c3:" + c3);
        System.out.println("c4:" + c4);
        System.out.println("c5:" + c5);
        System.out.println("c6:" + c6);
        System.out.println("c7:" + c7);
        System.out.println("c8:" + c8);
        System.out.println("c9:" + c9);

        // 元素类型相同且维度一致,就是同一个Class
        int[] a = new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }

    /**
     * 获取类的信息
     */
    @Test
    public void getClassInfoTest()
            throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException,
            InstantiationException, IllegalAccessException {
        Class c1 = Class.forName("main.java.per.learning.reflection.User");

        System.out.println("===================类的名字===================");
        // 获取类的名字
        System.out.println(c1.getName()); // 包名 + 类名
        System.out.println(c1.getSimpleName()); // 类名

        System.out.println("===================类的属性===================");
        // 获取属性
        Field[] fields = c1.getFields(); // public 属性
        Field hobby = c1.getField("hobby"); // 获取指定的public属性
        System.out.println(hobby);
        for (Field field : fields) {
            System.out.println("getFields:" + field.getName());
        }

        Field name = c1.getDeclaredField("name"); // 获取指定的属性
        System.out.println(name);
        Field[] declaredFields = c1.getDeclaredFields(); // 所有属性
        for (Field declaredField : declaredFields) {
            System.out.println("getDeclaredFields:" + declaredField);
        }

        System.out.println("===================类的方法===================");
        // 获取方法
        Method[] methods = c1.getMethods(); // 获取本类及父类的public 方法
        for (Method method : methods) {
            System.out.println("getMethods:" + method);
        }

        Method[] declaredMethods = c1.getDeclaredMethods(); // 获取本类所有方法
        for(Method declaredMethod : declaredMethods){
            System.out.println("getDeclaredMethods:" + declaredMethod);
        }

        // 获取指定方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        System.out.println("===================类的构造器===================");
        // 获取构造器
        Constructor[] constructors = c1.getConstructors(); // 获取public 构造方法
        for (Constructor constructor : constructors) {
            System.out.println("getConstructors:" + constructor);
        }

        Constructor[] declaredConstructors = c1.getDeclaredConstructors(); // 获取所有构造方法
        for (Constructor constructor : declaredConstructors) {
            System.out.println("getDeclaredConstructors:" + constructor);
        }

        //获取指定构造方法
        Constructor constructor1 = c1.getConstructor(String.class, int.class, String.class); // public
        System.out.println(constructor1);
        Constructor constructor2 = c1.getDeclaredConstructor(String.class); // 已定义的任意构造方法
        System.out.println(constructor2);
        constructor2.setAccessible(true);
        User user1 = (User)constructor2.newInstance("张三");
        System.out.println(user1);
    }

    /**
     * 通过反射操作类/对象
     */
    @Test
    public void manipulateClassTest()
            throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
            IllegalAccessException {
        // 获取Class对象
        Class c1 = Class.forName("main.java.per.learning.reflection.User");
        // 获取类的构造方法
        Constructor constructor = c1.getDeclaredConstructor(); // 无参构造(需要有参构造就传相应参数)
        // 获取类的对象
        User user = (User)constructor.newInstance();
        // 获取方法,以setName为例
        Method testFunc = c1.getDeclaredMethod("testFunc", String.class);

        // 调用普通方法,private方法/属性需要关闭权限检查
        testFunc.setAccessible(true); // private方法需要关闭权限检查
        testFunc.invoke(user, "测试方法调用");

        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(user, "张三");

        Method setHobby = c1.getDeclaredMethod("setHobby", String.class);
        setHobby.invoke(user, "橄榄球");
        
        System.out.println(user);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值