一、概念定义
反射机制:反射提供了一种动态的功能,这种动态功能非常强大。它主要体现 在通过反射相关的API就可以知道一个陌生Java类的所有信息,包括属性、方法、构造器等。而且元素完全可以在运行时动态的进行创建或调用,而不必在JVM运行时就进行确定。即运行状态中对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能即反射机制。
反射机制也是Java被视为动态语言的关键原因,提供以下功能:
(1)在运行时判断任意一个对象所属的类
(2)在运行时构造任意一个类对象
(3)在运行时判断任意一个类所具有的成员变量和方法
(4)在运行时调用任一个对象的方法
(5)在运行时创建新类对象
二、类的加载分析
1、 Java用Class类代表所有的类,方便了开发者掌控类信息。通过Class开发者可以得到属性(Field)、方法(Method)、构造器(Constructor)、修饰符(Modifier)等信息。在动态获取这些信息以后,开发者就可以用该Class创建实例、调用方法、访问方法、访问属性等操作,这也是反射的主要用途。反射机制的API主要集中在java.lang.reflect包下面。
通过上面的一段话,我们知道Class是用来记录一个类的各种信息的,它伴随类的加载而创建,问题随之而来:类会在什么时候被加载到JVM中呢?总结以下几种情况:
(1)需要使用该类创建对象,如下所示:
Student stu = new Student();
(2)访问该类的静态成员,如下所示:
2、不论以什么样的方式类一旦被加载到JVM中,就会为它创建一个Class类实例对象。所以问题又来了,开发者如何得到 这个Class对象呢?总结以下三种途径:(3)使用Class类的静态forName()方法,动态加载一个指定类名的类,如下所示:System.out.println(Student.count);
Class.forName("com.test.Student");
三、应用举例(1)Object类的getClass()方法,它返回的是对象的运行时类的Class对象。
Student stu = new Student(); Class<?> clazz = stu.getClass();
(2)类的Class静态属性,每个类都会有这个静态属性通过它可以获取到Class对象
Class<?> clazz = Student.class;
(3)Class的forName()方法,该方法返回值就是Class类型,也就是动态导入类的Class对象的引用
Class<?> clazz = Class.forName("com.test.Student");
(参考博客http://blog.csdn.net/yongjian1092/article/details/7364451,在此声明):
public class Test {
public int pubIntField;
public String pubStringField;
private int prvIntField;
public Test(){
Log("Default Constructor.");
}
Test(int arg1, String arg2){
pubIntField = arg1;
pubStringField = arg2;
Log("Constructor with parameters.");
}
public void setIntField(int val){
this.prvIntField = val;
}
public int getIntField(){
return prvIntField;
}
private void Log(String msg) {
System.out.println("Test: " + msg);
}
}
public class ExtendTest extends Test {
public int pubIntExtendField;
public String pubStringExtendField;
private int prvIntExtendField;
public ExtendTest(){
Log("Default Constructor.");
}
ExtendTest(int arg1, String arg2){
pubIntExtendField = arg1;
pubStringExtendField = arg2;
Log("Constructor with parameters.");
}
public void setIntExtendField(int val){
this.prvIntExtendField = val;
}
public int getIntExtendField(){
return prvIntExtendField;
}
private void Log(String msg){
System.out.println("ExtendTest: " + msg);
}
}
1、通过反射机制获取Class对象
调用getClass | Boolean var1 = true; Class<?> classType2 = var1.getClass(); System.out.println(classType2); 输出:class java.lang.Boolean |
运用.class 语法 | Class<?> classType4 = Boolean.class; System.out.println(classType4); 输出:class java.lang.Boolean |
运用static method Class.forName() | Class<?> classType5 = Class.forName("java.lang.Boolean"); System.out.println(classType5); 输出:class java.lang.Boolean |
运用primitive wrapper classes的TYPE 语法 这里返回的是原生类型,和Boolean.class返回的不同 | Class<?> classType3 = Boolean.TYPE; System.out.println(classType3); 输出:boolean |
/**获取类的Class对象*/
//1、调用getClass()方法来获取Class
ExtendTest test = new ExtendTest(12,"Ok");
Class<?> classType = test.getClass();
System.out.println(classType);
//2、运用.class语法
Class<?> classType1 = ExtendTest.class;
System.out.println(classType1);
//3、运用static method Class.forName()
Class<?> classType2 = Class.forName("ReflectionTest.ExtendTest");
System.out.println(classType2);
System.out.println();
2、通过反射机制获取类的Fields属性
public FieldgetField(String name) | 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段 |
public Field[] getFields() | 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段 |
public FieldgetDeclaredField(Stringname) | 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段 |
public Field[] getDeclaredFields() | 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段 |
/**获取类的Fields,通过反射机制获取类的某个属性
* getFields()与getDeclaredFields()区别:
* (1)getFields()返回的是声明为public的属性,包括父类中定义
* (2)getDeclaredFields()返回的是指定类定义的所有定义的属性,不包括父类的
* */
//1、通过getFields()方法获取属性
Field[] fields = classType.getFields();
for(Field field : fields)
System.out.println(field);
System.out.println();
//2、通过getDeclaredFields()方法获取属性
fields = classType.getDeclaredFields();
for(Field field : fields)
System.out.println(field);
System.out.println();
3、通过反射机制获取类的Method方法
public MethodgetMethod(String name,Class<?>... parameterTypes) | 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法 |
public Method[] getMethods() | 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 |
public MethodgetDeclaredMethod(Stringname,Class<?>... parameterTypes) | 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法 |
public Method[] getDeclaredMethods() | 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法 |
/**获取类的Method,通过反射机制获取类的某个方法*/
//1、使用getMehtods()方法获取函数
Method[] methods = classType.getMethods();
for(Method method : methods)
System.out.println(method);
System.out.println();
//2、使用getDeclaredMethod获取函数
methods = classType.getDeclaredMethods();
for(Method method : methods)
System.out.println(method);
System.out.println();
4、通过反射机制获取类的Constructor构造函数
public Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法 |
public Constructor<?>[] getConstructors() | 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法 |
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法 |
public Constructor<?>[] getDeclaredConstructors() | 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法 |
/**获取类的Constructor,通过反射机制获取类的构造器*/
//1、使用getConstructors获取构造器
Constructor<?>[] constructors = classType.getConstructors();
for(Constructor<?> constructor : constructors)
System.out.println(constructor);
System.out.println();
//2、使用getDeclaredConstructor获取构造器
constructors = classType.getDeclaredConstructors();
for(Constructor<?> constructor : constructors)
System.out.println(constructor);
System.out.println();
5、通过反射机制创建类实例、调用类函数,通过反射机制调用类函数
调用无自变量ctor | 1、调用类的Class对象的newInstance方法,该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败. Class<?> classType = ExtendType.class; Object inst = classType.newInstance(); System.out.println(inst); 输出: Type:Default Constructor ExtendType:Default Constructor
2、调用默认Constructor对象的newInstance方法 Class<?> classType = ExtendType.class; Constructor<?> constructor1 = classType.getConstructor(); Object inst = constructor1.newInstance(); System.out.println(inst); 输出: Type:Default Constructor ExtendType:Default Constructor com.quincy.ExtendType@1006d75 |
调用带参数ctor | 3、调用带参数Constructor对象的newInstance方法 Constructor<?> constructor2 = classType.getDeclaredConstructor(int.class, String.class); Object inst = constructor2.newInstance(1, "123"); System.out.println(inst); 输出: Type:Default Constructor ExtendType:Constructor with parameters com.quincy.ExtendType@15e83f9 |
Object instance = classType.newInstance();
Method logMethod = classType.getDeclaredMethod("Log", String.class);
logMethod.invoke(instance, "OK?");
6、通过反射机制获取/设置类属性值
Field intField = classType.getField("pubIntExtendField");
intField.setInt(instance, 100);
int val = intField.getInt(instance);