通过反射获取类的基本信息以及实例化对象

181 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

我们根据这篇文章中的示例类结构来完成下面内容的介绍。

获取类的基本信息

一个自定义类中包含很多信息,如包名、类名、父类、实现的接口等等。java 中的反射特性给我们提供了很多的api,我们来看一下。

Class clazz = Class.forName("xxxx.xxxx.xxxx.Student");
// 获取包名+类名
System.out.println(clazz.getName());
// 只获取类名
System.out.println(clazz.getSimpleName());
// 只获取包名
System.out.println(clazz.getPackage());
// 获取当前类的父类
System.out.println(clazz.getSuperclass());
// 判断当前类是否为内部类
System.out.println(clazz.isAnonymousClass());
// 判断一个类是否为另一个类的子类
System.out.println(Animal.class.isAssignableFrom(clazz));
// 判断当前类是否为抽象类
System.out.println(Modifier.isAbstract(clazz.getModifiers()));
// 判断当前结构是否是一个接口
System.out.println(clazz.isInterface());

实例化类对象的几种方式

我们使用反射的特性,调用类中的构造方法来完成示例化对象的操作。我们介绍以下三种方式。

调用类的无参构造方法来实例化对象:

Class<?> clazz = Student.class;
Student student;
 try {
    //调用该类的无参构造方法
    student = (Student) clazz.newInstance();
} catch (Exception e) {
    e.printStackTrace();
}

执行上述代码的时候,在终端会输出

non parameter construct method

这就代表,newInstance 方法会调用当前类的无参构造方法来完成对象的创建。

调用类的有参构造方法来实例化对象

我们依旧通过一个例子来看如何使用。

Class<?> clazz = Student.class;
Student student;
try {
    Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
    student = (Student) constructor.newInstance("Jack", 47);
} catch (Exception e) {
    e.printStackTrace();
}

上面代码中,clazz.getConstructor(String.class, int.class) 就是用来获取该Student 类中的参数类型为String 和int 的构造方法。

执行上述代码后,终端会输出结果为

age: 47 name: Jack

这代表在获取类的对象的时候,调用了类的有参构造函数。

如何获取一个类的所有构造方法

其实在一个类中,构造方法有时候会有很多,反射特性也提供了相应的api 来获取某个某个类的所有构造函数,同时我们也可以获得到构造函数中所需要的参数。我们继续通过例子来看一下。

Class<?> clazz = Student.class;
for (Constructor<?> constructor : clazz.getConstructors()) {
    for (Class<?> parameterType : constructor.getParameterTypes()) {
        System.out.println(parameterType);
    }
}

也就是通过clazz.getConstructors()就可以获取到类的所有的构造方法。

对于某个构造函数,调用getParameterTypes 方法就可以获得到这个构造方法的参数类型。

总结

这篇文章我们介绍了如何通过反射获取类的基本信息,以及如何通过反射构造实例化的对象。