Java反射详解(三)

上一篇博客: Java反射详解(二)

 写在前面:大家好!我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正,感谢大家的不吝赐教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油,冲鸭!

用知识改变命运,用知识成就未来!加油 (ง •̀o•́)ง (ง •̀o•́)ง

文章目录

前言

 之前两篇主要介绍了反射与 Class类 的关系以及通过 Class对象 我们可以获得什么信息以及可以做什么操作,还有如何通过反射获取 Class类 具体字段的信息以及具体方法的信息。本篇书接上文,继续进行梳理我们可以通过反射做什么。

创建对象

 通过 ClassnewInstance() 方法可以创建对象。这里需要注意该方法会调用类的默认的构造方法(即无参的 public 方法),如果我们操作的类没有无参构造方法,调用该方法会抛出 InstantiationException 异常。

java 复制代码
public class TestClass {
    @Test
    public void test() throws IllegalAccessException, InstantiationException {
        Class<Person> personClass = Person.class;
        Person person = personClass.newInstance();
        person.eat(); // 生物进食
    }
}

构造器相关方法

getConstructors()

getConstructors() 获取当前运行时类中所有 public 构造方法。

java 复制代码
public class TestClass {
    @Test
    public void test() {
        Class<Person> personClass = Person.class;
        Constructor<?>[] constructors = personClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor); // public ReflectionTest.Person()
        }
    }
}

getDeclaredConstructors()

 获取所有的构造器方法,包括 非public 的。

java 复制代码
public class TestClass {
    @Test
    public void test() {
        Class<Person> personClass = Person.class;
        Constructor<?>[] constructors = personClass.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
            /**
             * public ReflectionTest.Person()
             * private ReflectionTest.Person(java.lang.String,java.lang.String)
             */
        }
    }
}

其他几种方法

Constructor类的方法如下,这里列举几个主要的方法:

  • public Constructor getConstructor(Class<?>... parameterTypes) 获取指定参数类型的public构造方法。
  • public Constructor getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型的构造方法,包括 非public 的。
  • public Class<?>\[\] getParameterTypes() 返回构造函数的参数类型数组。
  • public Annotation\[\] getAnnotations() 返回构造函数的注解
  • public void setAccessible(boolean flag) 设置构造器是否可访问
  • public T newInstance(Object ... initargs) 通过构造器创建对象
  • public Class<?>\[\] getExceptionTypes() 返回构造方法声明抛出的异常类型
  • public int getModifiers() 返回构造器的修饰符

类的声明信息

Class还有很多方法可以获取类的声明信息,例如修饰符、父类、接口、注解等等,相关方法如下:

java 复制代码
​​​​​​​​​​//获取修饰符,返回值可通过Modifier类进行解读
​​​​​​​​public native int getModifiers()
​​​​​​​​//获取父类,如果为Object,父类为null
​​​​​​​​public native Class<? super T> getSuperclass()
​​​​​​​​//对于类,为自己声明实现的所有接口,对于接口,为直接扩展的接口,不包括通过父类继承的
​​​​​​​​public native Class<? >[] getInterfaces();
​​​​​​​​//自己声明的注解
​​​​​​​​public Annotation[] getDeclaredAnnotations()
​​​​​​​​//所有的注解,包括继承得到的
​​​​​​​​public Annotation[] getAnnotations()
​​​​​​​​//获取或检查指定类型的注解,包括继承得到的
​​​​​​​​public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
​​​​​​​​public boolean isAnnotationPresent(
​​​​​​​​                Class<? extends Annotation> annotationClass)​​

Class的类型信息

Class 代表的类型既可以是普通的类,也可以是内部类,还可以是基本类型、数组等等。可以通过一下方法检查 Class对象 的类型:

java 复制代码
public native boolean isArray()  //是否是数组
​​​​​​​​public native boolean isPrimitive()  //是否是基本类型
​​​​​​​​public native boolean isInterface()  //是否是接口
​​​​​​​​public boolean isEnum()  //是否是枚举
​​​​​​​​public boolean isAnnotation()  //是否是注解
​​​​​​​​public boolean isAnonymousClass()  //是否是匿名内部类
​​​​​​​​public boolean isMemberClass()  //是否是成员类,成员类定义在方法外,不是匿名类
​​​​​​​​public boolean isLocalClass()  //是否是本地类,本地类定义在方法内,不是匿名类​​

反射与数组

Class类 中还导入了 java.lang.reflect 包中专门针对数组的 Array类 ,注意该类与 java.util.Arrays 不同。 java.lang.reflect 包中的 Array类 提供了对于数组的一些反射支持,主要方法如下:

java 复制代码
​​​​​​​​​​//创建指定元素类型、指定长度的数组
​​​​​​​​public static Object newInstance(Class<? > componentType, int length)
​​​​​​​​//创建多维数组
​​​​​​​​public static Object newInstance(Class<? > componentType, int... dimensions)
​​​​​​​​//获取数组array指定的索引位置index处的值
​​​​​​​​public static native Object get(Object array, int index)
​​​​​​​​//修改数组array指定的索引位置index处的值为value
​​​​​​​​public static native void set(Object array, int index, Object value)
​​​​​​​​//返回数组的长度
​​​​​​​​public static native int getLength(Object array)
//除Object类型之外Array也支持以各种基本类型操作数组元素
​​public static native double getDouble(Object array, int index)
​​​​​​​​public static native void setDouble(Object array, int index, double d)
​​​​​​​​public static native void setLong(Object array, int index, long l)
​​​​​​​​public static native long getLong(Object array, int index)​​

反射与枚举

 对于枚举类型也有一个专门的方法用于获取所有的枚举常量。

java 复制代码
public T[] getEnumConstants()

总结

 其实还有很多方法没有列举出来,但是通过这三篇博客的概述我们可以深刻的体会到了反射的强大机制。基本我们想获取的信息或者想实现的操作都能够通过反射进行获取或执行。以上提到的只是反射的一些基础知识,最重要的我们如何看懂那些框架对反射的运用以及在特殊情况下我们如何通过反射完成相关的需求。

 这里还是特别说明一下,我们在日常开发中基本用不到反射。虽然说反射可以让我们的代码更加灵活,但是这也是建立在特殊情况的前提之下的。使用反射也增加了安全问题(更容易出现运行时错误,使用显式的类和接口编译器还可以帮助我们做类型检查,减少错误。使用反射只能在运行时才知道);性能也相对差一些,之前看到过一些处理方式是将通过反射获取的信息存储到缓存或者数据库中。


  1. 《Java编程的逻辑》
相关推荐
小bo波1 小时前
Java Swing 图形用户界面实验 —— 从算术练习到游戏开发的完整实践
java·课程设计·gui·游戏开发·扫雷·swing
咖啡八杯2 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
apocelipes4 小时前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
用户8356290780516 小时前
使用 Python 在 PDF 中创建与管理书签
后端·python
MeixianAgent11 小时前
Python 回测数据入口怎么验?历史 K 线入库前先做 5 个检查
后端·python
SamDeepThinking13 小时前
裁掉那个差程序员后,给你看团队里高手的代码:这个习惯,希望你有
java·后端·程序员
朕瞧着你甚好14 小时前
技术雷达 & Java 集成评估报告 — Apache Tika 3.3.1
java·ai编程
咕白m62514 小时前
用 Python 实现一键批量查找与替换 Excel 数据
后端·python
MacroZheng14 小时前
短短几天,暴涨2.8万Star!又一款编程神器开源!
java·人工智能·后端
SamDeepThinking15 小时前
函数式编程:用BiFunction消除多类型分支的代码重复
java·后端·面试