Java反射的概念
反射(Reflection),是指程序在运行期可以拿到一个对象的所有信息。
在程序中,如果我们要调用对象的方法或者是访问对象的字段,一般是使用对象的实例。
User user = new User();
user.getName();
那如果只有Object实例,怎么调用Person的方法?有一种方法是强转。
Object obj = new Object();
User user1 = (User) obj;
但是在使用强转的方法中,还是需要importUser类,否则编译还是无法通过。
因此在Java语言中,使用反射来解决在运行期,对某个实例一无所知的情况下,如何调用其方法。
反射
Java的数据类型分为基本数据类型和引用数据类型,所有的引用数据类型都是class。class(包括interface)的本质都是数据类型(Type)。
class是由JVM在执行过程中动态加载的。JVM在第一次读取到一种class类型时,将其加载进内存。
每加载一种class,JVM就为其将创建一个Class类型的实例。其中,Class类型是一个名叫Class的class,其定义如下:
public final class Class implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
/*
* Private constructor. Only the Java Virtual Machine creates Class objects.
* This constructor is not used and prevents the default constructor being
* generated.
*/
private Class(ClassLoader loader) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}
...
}
当JVM要加载User类时,首先读取User.class文件,然后为User类创建一个Class实例。
如果我们自己要
Class cls = new Class(User.class);
这里有一点要注意,由上面Class类型的定义可以看到,构造器是私有的,因此只能是在JVM内部创建,我们的Java程序无法像这样创建Class实例。
在JVM中,持有的每个Class实例都指向一个引用数据类型。一个Class实例包含了对应class的所有完整信息,包括类名、包名、父类、实现的接口、所有方法、字段等。所以只要有了Class实例,我们就可以通过Class获取到对应的Class的所有信息。
通过Class实例获取信息示例:
Class cls = User.class;
System.out.println(cls.getName());
System.out.println(cls.getPackage());
System.out.println(cls.getSuperclass());
// 获取所有public的field(包括父类)
Field[] fields = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
// 获取当前类的field(不包括父类)
Field[] fields2 = cls.getFields();
for (int i = 0; i < fields2.length; i++) {
System.out.println(fields2[i]);
}