类反射:
- JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
- 反射(Reflection)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查, 也称自审,并能直接操作程序的内部属性。例如,使用它能获得Java类中各成员的名称并显示出来。
- Java的这一能力在实际应用中应用得很多,在其它的程序语言中根本就不存在这一特性。例如,Pascal、C或者C++中就没有办法在程序中获得函数定义相关的信息。
- JavaBean是类反射的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过类反射动态的载入并取得Java组件(类)的属性。后面学习的各种框架,基本上都会有反射的使用。
接下来我将用代码的形式逐一演示类反射,带你玩转类反射!
反射使用的三个步骤
第一步:获得你想操作的类的java.lang.Class对象。在运行中的Java程序中,用java.lang.Class类来描述类和接口等。
第二步:调用诸如getDeclaredMethods的方法,取得该类中定义的所有方法的列表。
第三步:使用反射的API来操作这些信息。
获取Class对象的三种方式
★ 方式一
通过对象的getClass方法进行获取。这种方式需要具体的类和该类的对象,以及调用getClass方法。
★ 方式二
任何数据类型(包括基本数据类型)都具备着一个静态的属性class,通过它可直接获取到该类型对应的Class对象。这种方式要使用具体的类,然后调用类中的静态属性class完成,无需调用方法,性能更好。
★ 方式三(这种方式仅仅依赖于javaAPI中的String类,在开发中常用!)
通过Class.forName()方法获取。这种方式仅需使用类名,就可以获取该类的Class对象,更有利于扩展。
代码演示(代码演示中我们采用JUnit 测试工具来进行测试)
package cn.hncu.reflect;
import org.junit.Test;
//获取Class对象的三种方式
public class ReflectGetClass {
@Test//法1:通过 对象.getClass()
public void getClass1() {
Person p = new Person("Jack",22);
Class c = p.getClass();
System.out.println(c);
}
@Test//法2:通过类型---任何数据类型(包含基本数据类型)都拥有一个静态变量class
public void getClass2() {
Class c = Person.class;
System.out.println(c);
Class c2 = int.class;
System.out.println(c2);
}
@Test//法3:通过Class.forName直接获取---不依赖具体的类或对象(仅仅依赖String类,而我们做项目时通常把使用API中的类看成不是依赖的!)
public void getClass3() {
try {
Class c = Class.forName("cn.hncu.reflect.Person");//“类全名”的字符串形式
System.out.println(c);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//※法3是不依赖于被反射类或对象的,能够完全达到解藕的效果,是我们以后开发当中的首选策略
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
类的解剖(获取类的定义信息)
★ 获取类的方法
找出一个类中定义了些什么方法,这是一个非常有价值也非常基础的反射用法。
★ 获取类的构造器
找出一个类中定义的构造方法,构造器没有返回类型。
★ 获取类的属性字段
找出一个类中定义了哪些属性字段。
代码演示
package cn.hncu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.junit.Test;
//类的解剖:把一个类中的所有方法、属性、构造方法全部获取出来
public class ReflectDecompose {
private static final String className="cn.hncu.reflect.Student";
//private static final String className="cn.hncu.reflect.Person";
//1 c.getMethods()----获取的是当前类及其父类的公开方法---无法获取到私有方法
//2 c.getDeclaredMethods()----获取的是当前类自己定义的那些方法---包括私有的 但不包括父类中的方法
@Test//获取方法
public void fetchMethods() throws Exception{
Class c = Class.forName(className);
//Method ms[] = c.getMethods();//所能访问的方法和一个“Person p=new Person()”中的p对象一样
Method ms[] = c.getDeclaredMethods();
for(int i=0;i<ms.length;i++){
Method m = ms[i];
System.out.println("name: "+m.getName());
System.out.println("declaringClass: "+ m.getDeclaringClass());
Class paramTypes[] = m.getParameterTypes();
for(int j=0;j<paramTypes.length;j++){
System.out.println("param#"+j+": "+ paramTypes[j]);
}
Class returnType = m.getReturnType();
System.out.println("returnType: "+returnType);
Class excepts[] = m.getExceptionTypes();
for(int j=0;j<excepts.length;j++){
System.out.println("excepts#"+j+": "+ excepts[j]);
}
int modifiers = m.getModifiers();
System.out.println("modifiers: "+modifiers);
System.out.println("--------------");
}
}
//注意,构造方法都不包含父类的
//1 c.getConstructors()----获取的是当前类(注意不包含父类的)的公开构造方法---无法获取到私有方法
//2 c.getDeclaredConstructors()----获取的是当前类自己定义的构造方法---包括私有的
@Test//获取方法
public void fetchConstructors() throws Exception{
Class c = Class.forName(className);
//Constructor cons[] = c.getConstructors();//所能访问的方法和一个“Person p=new Person()”中的p对象一样
Constructor cons[] = c.getDeclaredConstructors();
for(int i=0;i<cons.length;i++){
Constructor con = cons[i];
System.out.println("name: "+con.getName());
System.out.println("declaringClass: "+ con.getDeclaringClass());
Class paramTypes[] = con.getParameterTypes();
for(int j=0;j<paramTypes.length;j++){
System.out.println("param#"+j+": "+ paramTypes[j]);
}
Class excepts[] = con.getExceptionTypes();
for(int j=0;j<excepts.length;j++){
System.out.println("excepts#"+j+": "+ excepts[j]);
}
int modifiers = con.getModifiers();
System.out.println("modifiers: "+modifiers);
System.out.println("--------------");
}
}
//1 c.getFields()----获取的是当前类和父类的公开属性---无法获取到私有属性
//2 c.getDeclaredFields()----获取的是当前类自己定义的属性---包括私有的
@Test//获取方法
public void fetchFields() throws Exception{
Class c = Class.forName(className);
//Field flds[] = c.getFields();
Field flds[] = c.getDeclaredFields();
for(int i=0;i<flds.length;i++){
Field fld = flds[i];
System.out.println("name: "+fld.getName());
System.out.println("declaringClass: "+ fld.getDeclaringClass());
Class type = fld.getType();
System.out.println("type: "+ type);
int modifiers = fld.getModifiers();
System.out.println("modifiers: "+Modifier.toString(modifiers) );
System.out.println("--------------");
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
Class类中包含的主要三个需要解剖的东西:
Field[]—{Name,DeclaringClass,Type,Modifiers,(…annotation,genericType…)}
Constructor[]—{Name,DeclaringClass,Modifiers,ParameterTypes,ExceptionTypes(…annotation,genericType…)}
Method[]–{Name,DeclaringClass,ReturnType,Modifiers,ParameterTypes,ExceptionTypes(…annotation,genericType…)}
附上一张修饰符对应的二进制整数的图(来自JAVA–API)