一:什么是反射机制?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
说的更明白一点就是JAVA动态相关机制:Reflection,使用反射我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作慢于只直接执行相同的操作。
在说明反射机制前,先了解下Class对象.
二:Class 对象
Java有个Object 类,是所有Java 类的继承根源,声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。
Class 类十分特殊。它和一般类一样继承自Object,实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码”来观察Class 对象的实际生成时机(例如在Class的constructor内添加一个println()),这样是行不通的!因为Class并没有public constructor。Class是Reflection故事起源。针对任何您想探勘的类,唯有先为它产生一个Class 对象.
JAVA中获取Class对象有3种方式:public
final
class
Class<T>
implements
Serializable,
java.lang.reflect.GenericDeclaration,
java.lang.reflect.Type,
java.lang.reflect.AnnotatedElement {
private
Class() {}
public
String toString() {
return
( isInterface() ?
"interface "
: (isPrimitive() ?
""
:
"class "
))
+ getName();
}
上述为Class class片段。注意它的private Class() {},意指不允许任何人经由编程方式产生Class object。object 只能由JVM 产生。
获取Class对象后,我们需要从Class中获取信息
- 对象的
getClass()
方法;- 类的
.class
(最安全/性能最好)属性;- 运用
Class.forName(String className)
动态加载类,className
需要是类的全限定名(最常用).
Class
类提供了大量的实例方法来获取该Class对象所对应的详细信息,Class类大致包含如下方法,其中每个方法都包含多个重载版本,常用的如下获取类的构造器
public Constructor<?>[] getConstructors() 返回类中所有的public构造器集合,默认构造器的下标为0
public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回指定public构造器,参数为构造器参数类型集合
public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造器,包括私有
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器
获取类的成员变量
成员变量用Field类进行封装,主要的方法非常的类似:
public Field getDeclaredField(String name) 获取任意指定名字的成员
public Field[] getDeclaredFields() 获取所有的成员变量
public Field getField(String name) 获取任意public成员变量
public Field[] getFields() 获取所有的public成员变量
获取类的方法
public Method[] getMethods() 获取所有的共有方法的集合
public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合
public Method[] getDeclaredMethods() 获取所有的方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法调用方法:invoke;
构造对象
利用newInstance创建对象:调用的类必须有无参的构造器.
静态的方法属性初始化,是在加载类的时候初始化。而非静态方法属性初始化,是new类实例对象的时候加载。
因此三种方式生成Class对象,其实只有一个Class对象。在生成Class对象的时候,首先判断JVM中是否已经加载。
JVM虚拟机为每种类型管理一个独一无二的Class对象,也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。