java反射机制调用带参数的方法_Java反射机制:跟着代码学反射

1. 前言

在OOP的世界里,万物皆对象。也就是说,我们可以将任何东西抽象成一个对象。

比如人,可以抽象成一个Person类,通过new Person()来实例化一个对象;再比如鸭子,可以抽象成一个Duck类,也可以对其进行实例化……那么这一个个类本身是不是也可以抽象成一个类呢?Java提供了一个特殊的类Class,用来描述类的内部信息,是反射的核心类。

下图是本篇讲述内容:

java反射机制调用带参数的方法_Java反射机制:跟着代码学反射_第1张图片

2. Java反射机制概述

Java反射(Reflection)允许应用程序在运行时借助于反射API,来获取所有类或接口的内部信息,并且能直接操作任意对象的内部属性及方法。反射机制的核心类为java.lang.Class。类加载完后,会在堆内存的方法区中产生一个Class类型的对象。

Class类没有公开的构造函数,是由类加载器的defineClass方法构造而成。所以Class对象不是“new”出来的,而是通过方法来获取的。

这个Class对象具有类的完整结构信息,并且一个类只有一个Class对象。

3. 获取Class对象

获取Class对象有以下四种方式:通过类对象获取;

通过类直接调用class获取;

通过Class.forName获取;

通过类加载器获取。

下面使用代码展示获取 Person 类的Class对象的四种方式:@Test

public void testClassFor() {

// 1.通过类实例获取

Person person = new Person();

Class extends Person> clazz1 = person.getClass();

System.out.println("01 - " + clazz1);

// 2.通过类直接调用class获取

Class clazz2 = Person.class;

System.out.println("02 - " + clazz2);

// 3.通过Class.forName获取

Class> clazz3 = null;

try {

clazz3 = Class.forName("io.github.gozhuyinglong.reflection.Person");

} catch (ClassNotFoundException e) {

// 当找不到指定类时,会抛出此异常

e.printStackTrace();

}

System.out.println("03 - " + clazz3);

// 4.通过类加载器获取

ClassLoader classLoader = this.getClass().getClassLoader();

Class> clazz4 = null;

try {

clazz4 = classLoader.loadClass("io.github.gozhuyinglong.reflection.Person");

} catch (ClassNotFoundException e) {

// 当找不到指定类时,会抛出此异常

e.printStackTrace();

}

System.out.println("04 - " + clazz4);

// hashCode相等,说明这四种方式获取的是同一个实例

System.out.println("05 - " + clazz1.hashCode());

System.out.println("06 - " + clazz2.hashCode());

System.out.println("07 - " + clazz3.hashCode());

System.out.println("08 - " + clazz4.hashCode());

}

输出结果:01 - class io.github.gozhuyinglong.reflection.Person

02 - class io.github.gozhuyinglong.reflection.Person

03 - class io.github.gozhuyinglong.reflection.Person

04 - class io.github.gozhuyinglong.reflection.Person

05 - 721748895

06 - 721748895

07 - 721748895

08 - 721748895

通过上面的输出结果可以看出,这四个Class对象的hashCode相同,说明使用这四种方式获取的是同一个对象。

4. 一些特殊的类和接口的Class对象

在源码注释中提到一些特殊的类和接口:枚举是一种类。

注解是一种接口。

数组也属于一个反映为Class对象的类。具有相同元素类型和维数的数组,也具有相同的Class对象(也就是说,元素类型不同,或数组维数不同,其Class对象也不同)。

原始Java类型(boolean, byte, char, short, int, long, float,double)和关键字 void 也表示为Class对象。

下面通过代码来验证:@Test

public void testClassOther() {

// 枚举是一种类

Class clazz1 = PersonEnum.class;

System.out.println("01 - " + clazz1);

// 注解是一种接口

Class clazz2 = PersonAnnotation.class;

System.out.println("02 - " + clazz2);

// 数组也属于一个反应 Class 实例的类

Person[] personArray3 = new Person[1];

Class extends Person[]> clazz3 = personArray3.getClass();

System.out.println("03 - " + clazz3);

// 具有相同元素类型和维数的数组,也具有相同的 Class 实例

Person[] personArray4 = new Person[4];

Class> clazz4 = personArray4.getClass();

Person[][] personArray5 = new Person[1][];

Class> clazz5 = personArray5.getClass();

// 两个一维数组的 hashCode 相等,说明是同一实例

System.out.println("04 - " + clazz3.hashCode());

System.out.println("05 - " + clazz4.hashCode());

// 一维数组与二维数组的 hashCode 不相等,说明不是同一实例

System.out.println("06 - " + clazz5.hashCode());

// 原始 Java 类型和关键字 void 也表示为 Class 实例

Class clazz6 = int.class;

System.out.println("07 - " + clazz6);

Class clazz7 = double.class;

System.out.println("08 - " + clazz7);

Class clazz8 = void.class;

System.out.println("09 - " + clazz8);

}

输出结果:01 - class io.github.gozhuyinglong.re

你可能感兴趣的:(java反射机制调用带参数的方法_Java反射机制:跟着代码学反射)