java反射学习

本文详细介绍了Java反射机制,通过Hutool工具库展示了获取Class对象的三种方式,以及如何获取类的名称信息。接着探讨了获取和操作字段、方法和构造器的方法,包括invoke方法的使用。此外,还涉及了类型检查、强制类型转换以及构造对象的过程。文章最后提到了反射在实际工作中的应用,强调避免重复造轮子,提高开发效率。
摘要由CSDN通过智能技术生成

学习反射,在工作中可以直接使用Hutool的反射工具类,避免重复造轮子。

获取Class对象的三种方式

        ReflectTestPOJO dog = new ReflectTestPOJO();
        // 获取Class对象方式-:实例.getClass()
        Class<? extends ReflectTestPOJO> dogClass = dog.getClass();
        // 获取Class对象方式二:类名.class;
        Class<ReflectTestPOJO> dogClass2 = ReflectTestPOJO.class;

        // 获取Class对象方式三: Class.forName("com.szh.pojo.ReflectTestPOJO");
        Class<?> dogClass3 = Class.forName("com.szh.pojo.ReflectTestPOJO");
        System.out.println("====================");
        System.out.println(dogClass+":"+dogClass2+":"+dogClass3);

获取名称信息

        System.out.println("====名称信息===");
        System.out.println("getName():==>"+dogClass3.getName());
        System.out.println("getSimpleName():==>"+dogClass3.getSimpleName());
        System.out.println("getCanonicalName():==>"+dogClass3.getCanonicalName());
        System.out.println("getName():==>"+dogClass3.getPackage());

输出

getName():>com.szh.pojo.ReflectTestPOJO
getSimpleName():
>ReflectTestPOJO
getCanonicalName():>com.szh.pojo.ReflectTestPOJO
getName():
>package com.szh.pojo

各个方法异同
在这里插入图片描述

获取字段信息

  System.out.println("====字段信息===");
        System.out.println("返回所有的public字段(包括父类)数组--->"+ Arrays.toString(dogClass3.getFields()));
        System.out.println("返回本类的所有字段(包含私有)数组--->"+ Arrays.toString(dogClass3.getDeclaredFields()));
        System.out.println("返回本类或者父类中指定名称的共有字段,找不到抛出异常--->"+dogClass3.getField("publicName"));
        System.out.println("返回本类指定名称的字段(包含私有),找不到抛出异常--->"+dogClass3.getDeclaredField("privateName"));

        System.out.println("======操作字段值=======");
        Field privateName = dogClass3.getDeclaredField("privateName");
        Field publicNameField = dogClass.getField("publicName");
        System.out.println("获取某个字段的名称---->"+privateName.getName());
        // 忽略java的访问检查机制
        privateName.setAccessible(true);
        publicNameField.setAccessible(true);
        System.out.println("判断当前程序是否对该字段有访问权限---->"+privateName.isAccessible());
        System.out.println("判断当前程序是否对publicNameField有访问权限---->"+publicNameField.isAccessible());
        System.out.println("获取该字段的字段值----->"+publicNameField.get(dog));
        System.out.println("获取该字段的字段值----->"+privateName.get(dog));
        System.out.println("修改该字段值");
        publicNameField.set(dog,"修改public字段值");
        System.out.println("修改之后的字段值----->"+publicNameField.get(dog));

        System.out.println("返回字段的修饰符----->"+publicNameField.getModifiers());
        System.out.println("返回字段的类型----->"+publicNameField.getType());
        System.out.println("返回字段的注解信息----->"+publicNameField.getAnnotatedType());

输出

====字段信息===
返回所有的public字段(包括父类)数组--->[public java.lang.String com.szh.pojo.ReflectTestPOJO.publicName, public java.lang.String com.szh.pojo.Father.fatherPublicFatherName]
返回本类的所有字段(包含私有)数组--->[public java.lang.String com.szh.pojo.ReflectTestPOJO.publicName, private java.lang.String com.szh.pojo.ReflectTestPOJO.privateName, private static java.lang.String com.szh.pojo.ReflectTestPOJO.staticPrivateName, private static final java.lang.String com.szh.pojo.ReflectTestPOJO.STATIC_FINAL_PRIVATE_NAME]
返回本类或者父类中指定名称的共有字段,找不到抛出异常--->public java.lang.String com.szh.pojo.ReflectTestPOJO.publicName
返回本类指定名称的字段(包含私有),找不到抛出异常--->private java.lang.String com.szh.pojo.ReflectTestPOJO.privateName
======操作字段值=======
获取某个字段的名称---->privateName
判断当前程序是否对该字段有访问权限---->true
判断当前程序是否对publicNameField有访问权限---->true
获取该字段的字段值----->null
获取该字段的字段值----->privateName
修改该字段值
修改之后的字段值----->修改public字段值
返回字段的修饰符----->1
返回字段的类型----->class java.lang.String
返回字段的注解信息----->sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@355da254

其他相关方法,可以看Class类源码。

方法信息

        System.out.println("====方法信息===");
        System.out.println("返回所有的public方法(包括父类)数组--->"+ Arrays.toString(dogClass3.getMethods()));
        System.out.println("返回本类的所有方法(包含私有)数组--->"+ Arrays.toString(dogClass3.getDeclaredMethods()));
        System.out.println("返回本类或者父类中指定名称和参数类型的共有方法,找不到抛出异常--->"+dogClass3.getMethod("staticMethod",String.class));
        System.out.println("返回本类指定名称的方法(包含私有),找不到抛出异常--->"+dogClass3.getDeclaredMethod("staticMethod",String.class));

输出结果

====方法信息===
返回所有的public方法(包括父类)数组--->[public java.lang.String com.szh.pojo.ReflectTestPOJO.toString(), public static void com.szh.pojo.ReflectTestPOJO.instanceMethod(java.lang.String), public static void com.szh.pojo.ReflectTestPOJO.staticMethod(java.lang.String), public static void com.szh.pojo.Father.fatherStaticMethod(java.lang.String), public static void com.szh.pojo.Father.fatherInstanceMethod(java.lang.String), public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
返回本类的所有方法(包含私有)数组--->[public java.lang.String com.szh.pojo.ReflectTestPOJO.toString(), public static void com.szh.pojo.ReflectTestPOJO.instanceMethod(java.lang.String), public static void com.szh.pojo.ReflectTestPOJO.staticMethod(java.lang.String)]
返回本类或者父类中指定名称和参数类型的共有方法,找不到抛出异常--->public static void com.szh.pojo.ReflectTestPOJO.staticMethod(java.lang.String)
返回本类指定名称的方法(包含私有),找不到抛出异常--->public static void com.szh.pojo.ReflectTestPOJO.staticMethod(java.lang.String)

invoke方法

        Method staticMethod = dogClass3.getMethod("staticMethod", String.class);
        // 入参method为静态方法,obj被忽略,可以为null,args可以为null。方法返回是Object返回,若抛出异常,
        // 异常被包装为InvocationTargetException,可通过getCause方法得到原异常
        try {
            Object invoke = staticMethod.invoke(null, "123");
            System.out.println(invoke);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

注意:和获取字段信息类似,可以获取修饰符,参数,返回值,注解等信息

构造方法

 System.out.println("====创建对象和构造方法===");

        ReflectTestPOJO reflectTestPOJO = dogClass.newInstance();
        // 会调用默认构造方法,若类没有无参构造,则抛出异常
        System.out.println("通过放射获取的对象,调用方法:---->"+reflectTestPOJO.toString());

        System.out.println("====获取构造方法信息===");
        System.out.println("返回所有的public构造方法,数组--->"+ Arrays.toString(dogClass3.getConstructors()));
        System.out.println("返回本类的所有构造方法(包含私有)数组--->"+ Arrays.toString(dogClass3.getDeclaredConstructors()));
        System.out.println("返回指定参数的public构造方法,找不到抛出异常--->"+dogClass3.getConstructor());
        System.out.println("返回指定参数的构造方法(包含私有),找不到抛出异常--->"+dogClass3.getDeclaredConstructor(new Class[]{String.class,String.class}));

        // 通过构造函数创建对象
        Constructor<?> declaredConstructor = dogClass3.getDeclaredConstructor(new Class[]{String.class, String.class});
        declaredConstructor.setAccessible(true);
        Object o = declaredConstructor.newInstance("2222", "1111");
        System.out.println(Integer.toString(o.hashCode()));

输出

====创建对象和构造方法===
通过放射获取的对象,调用方法:---->1581781576
====获取构造方法信息===
返回所有的public构造方法,数组--->[public com.szh.pojo.ReflectTestPOJO(), public com.szh.pojo.ReflectTestPOJO(java.lang.String)]
返回本类的所有构造方法(包含私有)数组--->[public com.szh.pojo.ReflectTestPOJO(), private com.szh.pojo.ReflectTestPOJO(java.lang.String,java.lang.String), public com.szh.pojo.ReflectTestPOJO(java.lang.String)]
返回指定参数的public构造方法,找不到抛出异常--->public com.szh.pojo.ReflectTestPOJO()
返回指定参数的构造方法(包含私有),找不到抛出异常--->private com.szh.pojo.ReflectTestPOJO(java.lang.String,java.lang.String)
1725154839

注意:Constructor还有很多方法,可以获取关于构造方法的很多信息。比如:参数,修饰符,注解。

类型检查和强制类型转换

    System.out.println("======类型检查和类型转换======");

        List<String> list =new ArrayList<>();
        if (list instanceof ArrayList){
            System.out.println("arrayList");
        }
        // 动态检查,
        if (dogClass2.isInstance(list)){
            System.out.println("这行不会走");
        }
        // 动态的时候,不知道能不能强制类型转换
        dogClass3.isAssignableFrom(List.class);
        System.out.println("检查参数类型cls能够给当前Class类型的变量:"+dogClass3.isAssignableFrom(List.class));

输出

======类型检查和类型转换======
arrayList
检查参数类型cls能够给当前Class类型的变量:false

类的class信息

在这里插入图片描述

类的声明信息,反射和数组,反射和枚举,类的加载,等参考《java编程的逻辑》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值