Reflection Mechanism
Java 反射机制
LiFan(李凡)
Chengdu University of Information Technology
The Department Of Computer Science
2005
What is the reflection?
? 反射 (reflection)又称为自省 (introspection),
是 Java语言提供的一种通过类的 Class对象获
取类的全部成员和类所属的类型 (类的超类
和实现的接口 )信息的机制
? 反射可用于实现以下两种功能,
(1) 创建类型浏览器,获取类型的结构信息
(2) 动态创建和操作对象
在使用各种面向对象设计方法都不能实现设
计需求的情况下才使用反射!
java.lang.Class Class
? 在 Java语言中,类 java.lang.Class用于表示
类型的定义,也声明了与反射相关的各种方

? 任何类、接口、数组或基本数据类型都提供
了静态的 类 Class的对象引用 class
String.class Cloneable.class
int[].class double.class
Methods for Class Objects
? 获取指定类型的 Class对象是进行反射操作的
起点
? 可通过以下 4种方法获取类型的 Class对象,
(1) 调用类 Object中的 getClass()方法
(2) 访问类型的静态域 <类型 >.class
(3) 调用 Class.forName(String className)方法
(4) 调用 Class对象的 getClasses()方法返回嵌套
类或接口的 Class对象
int[] a={10,100,1000};
Class intArrayClass=a.getClass();
int[] a={10,100,1000};
Class intArrayClass=a.class;
Class jdbcDriverCls=Class.forName(“com.mysql.jdbc.Driver”);
class A{
public class B{……}
……
}
Class bClass=A.class.getClasses()[0];
Methods for Type Kind
? 该类提供了以下方法用于判断 Class对象的
类型,
public boolean isInterface()
public boolean isArray()
public boolean isPrimitive()
public void showKind(Class classObj){
if(classObj.isInterface())
System.out.println(“It is an interface type”);
else if(classObj.isArray())
System.out.println(“It is an array type”);
else if(classObj.isPrimitive())
System.out.println(“It is a primitive type”);
else System.out.println(“It is a class type”);
}
showKind(String.class);
showKind(Serializable.class);
showKind(byte[].class);
showKind(int.class);
It is a class type
It is an interface type
It is an array type
It is a primitive type
Methods for Type Hierarchy
? 类 Class声明了以下方法用于获取类的父类
和实现的接口信息
public Class[] getInterfaces()
public Class getSuperClass()
? 类 Class声明了以下方法用于获取类的修饰
符信息
public int getModifiers()
Methods for Type Hierarchy
? 类 Class声明了以下方法用于获取数组元素
的类型信息,非数组类型则返回 null
public Class getComponentType()
? 类 Class声明了以下方法用于获取嵌套类所
在的外层类信息
public Class getDeclaringClass()
java.lang.reflect.Modifier Class
? java.lang.reflect包 定义了各种与反射相关的
类和接口
? 类 Modifier声明了各种表示修饰符类型的常
量和判断方法,
static final int FINAL
static final int PUBLIC
static boolean isProtected(int mod)
static boolean isVolatile(int mod)
public abstract class Outer{
public static final class Inner {……}
……
}
public class OuterExt extends Outer{
……
}
Class c0 = OuterExt.class.getSuperClass();
int m = c0.getModifiers();
boolean isAbstract = Modifier.isAbstract(m);
boolean isPublic = Modifier.isPublic(m);
Class c1 = c0.getClasses()[0];
boolean isFinal = Modifier.isFinal(c1.getModifiers());
true
true
true
Array Class Name
? 数组的类名由一个或多个左方括号,[”和表示数组
元素类型的字符构成,左方括号,[”的个数表示数
组的维数
B byte C char F float
S short Z boolean D double
I int L<类名 >; 类或接口
J long
? 类 Class声明了以下方法用于获取类型名
public String getName()
int[][] a=new int[5][];
String[] b=new String[10];
boolean[] c=new boolean[5];
Boolean[] d=new Boolean[5];
System.out.println(a.getClass().getName());
System.out.println(b.getClass().getName());
System.out.println(c.getClass().getName());
System.out.println(d.getClass().getName());
[[I
[Ljava.lang.String;
[Z
[Ljava.lang.Boolean;
Nested Type Name
? 嵌套类型中 成员类型的完全限定名 由所属外
层类型的完全限定名和成员类型名构成,中
间用字符,$”分隔
<外层类型完全限定名 >$<成员类型名 >
package test;
class A{
public class B{……}
……
}
Class bClass=A.class.getClasses()[0];
System.out.println(bClass.getName());
test.A$B
Classes for Class Members
? java.lang.reflect包 中定义了用于表示类或接
口的各种成员的类和接口
java.lang.reflect.Member(接口 )
java.lang.reflect.Constructor(类 )
java.lang.reflect.Field(类 )
java.lang.reflect.Method(类 )
Member
Constructor Field Method
java.lang.reflect.Member Interface
? 该接口声明了以下方法用于获得成员所属的类的
Class对象
public Class getDeclaringClass()
? 该接口声明了以下方法用于获得成员的修饰符类型
public int getModifiers()
? 该接口声明了以下方法用于获得成员的名称,如构
造函数名、域名、方法名等
public String getName()
java.lang.reflect.Constructor Class
? 类 Constructor用于表示类的构造函数
? 该类声明了以下方法用于动态创建类的对象
public Object newInstance(Object[] args)
throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
class Student{
private String name;
private String no;
public Student(String name,String no){
this.name=name;
this.no=no;
}
}
Studentstu0 = new Studen (“Zhangsan”,“200103001”);
Constructor c = Student.class.getConstructor();
Object[] args = new Object[]{“Zhangsan”,“200103001”};
Student stu1 = (Student)c.newInstance(args);
java.lang.reflect.Field Class
? 类 Field用于表示类的域
? 该类声明了以下方法用于获取域的类型
public Class getType()
? 该类声明了以下方法用于获取域的值
public <Type> get<Type>(Object obj)
? 该类声明了以下方法用于设置域的值
public void set<Type>(<Type> value)
class Student{
public String name;
public int age;
public Student(String name,int age){
this.name=name;
this.age=age;
}
}
Student stu0 = new Student(“Zhangsan”,21);
Field ageField = Student.class.getField(“age”);
int ageValue = ageField.getInt(stu0);
ageField.setInt(25);
System.out.println(stu0.age);
25
java.lang.reflect.Method Class
? 类 Method用于表示类的方法,其作用类似
于 C语言中的函数指针
? 该类声明了以下方法用于动态调用指定对象
的方法,
public Object invoke(Object obj,Object[] args)
class Student{
public String name;
public int age;
public Student(String name,int age){
this.name=name;
this.age=age;
}
public String getName() { return name; }
}
Student stu0 = new Student(“Zhangsan”,21);
Method getName =
Student.class.getMethod(“getName”,new Class[0]);
String name = getName.invoke(stu0,new Object[0]);
System.out.println(name);
Zhangsan
Methods for Constructor Object
? 类 Class声明了以下方法用于得到类的构造函
数对象
public Constructor[] getConstructors()
public Constructor[] getDeclaredConstructors()
public Constructor getConstructor(Class[]
paramTypes)
public Constructor getDeclaredConstructor(Class[]
paramTypes)
Methods for Field Object
? 类 Class声明了以下方法用于得到类的域对象
public Field[] getFields()
public Field[] getDeclaredFields()
public Field getField(String fieldName)
public Field getDeclaredField(String fieldName)
Methods for Method Object
? 类 Class声明了以下方法用于得到类的域对象
public Method[] getMethods()
public Method[] getDeclaredMethods()
public Method getMethod(String methodName,
Class[] paramTypes)
public Method getDeclaredMethod (String
methodName,Class[] paramTypes)
Access Non-Public Members
? 类 java.lang.refelct.AccessibleObject是类
Field,Method和 Constructor的基类
? 该类声明了以下方法用于 强制禁止非公有
成员的可访问性检查
public boolean isAccessible()
public void setAccessible(boolean flag)
class Student{
private String name;
private int age;
public Student(String name,int age){
this.name=name;
this.age=age;
}
}
Student stu0 = new Student(“Zhangsan”,21);
Field ageField = Student.class.getDeclaredField(“age”);
int ageValue = ageField.getInt( tu0);
ageField.setInt(25);
System.out.println(stu0.age);
ageField.setAccessible(true);
java.lang.reflect.Array Class
? 类 Array用于动态创建和操作数组对象
? 该类声明了以下方法用于动态创建数组
static Object newInstance(Class type,int length)
? 该类声明了以下方法用于动态修改数组
static <Type> get<Type>(Object array,int index)
static void set<Type>(Object array,int index,
<Type> value)
int[] array0 = {0,1,2,3,4};
int[] array = Array.newInstance(int.class,5);
for(int i=0;i<array.length;i++)
Array.setInt(array,i,i);
FileClient.java
……
client=new Socket(serverAddr,port);
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
DataInputStream dis=new DataInputStream(client.getInputStream());
String fileName=null;
if(filePath.indexOf("\\")==-1)
fileName=filePath;
else
fileName=filePath.substring(filePath.lastIndexOf("\\")+1);
System.out.println("发送文件,"+fileName);
dos.writeUTF(fileName);
BufferedInputStream bis=
new BufferedInputStream(new FileInputStream(filePath));
int c=-1;
byte[] buffer=new byte[512];
while((c=bis.read(buffer))!=-1){
dos.write(buffer,0,c);
}
String answer=dis.readUTF();
System.out.println("服务器响应, "+answer);
……
发送文件名
发送文件数据
FileServer.java
……
server=new ServerSocket(bindPort,20,serverAddr);
System.out.println("信息:服务器启动成功,开始监听 ");
session=server.accept();
DataInputStream dis=new DataInputStream(session.getInputStream());
DataOutputStream dos=new DataOutputStream(session.getOutputStream());
String fileName=dis.readUTF();
System.out.println("准备接收文件, "+fileName);
BufferedOutputStream bos=
new BufferedOutputStream(new FileOutputStream(new File(dir,fileName)));
int c=-1;
byte[] buffer=new byte[512];
while((c=dis.read(buffer))!=-1){
if(c==1 && buffer[0]==-1) break;
bos.write(buffer,0,c);
}
bos.close();
dos.writeUTF("文件接收成功 !");
System.out.println("信息:服务器发回响应,正常关闭 ");
……
接收文件名
int c=-1;
byte[] buffer=new byte[512];
while((c=dis.read(buffer))!=-1){
bos.write(buffer,0,c);
}
接收文件数据
FileClient.java
……
client=new Socket(serverAddr,port);
DataOutputStream dos=new DataOutputStream(client.getOutputStream());
DataInputStream dis=new DataInputStream(client.getInputStream());
String fileName=null;
if(filePath.indexOf("\\")==-1)
fileName=filePath;
else
fileName=filePath.substring(filePath.lastIndexOf("\\")+1);
System.out.println("发送文件,"+fileName);
dos.writeUTF(fileName);
BufferedInputStream bis=
new BufferedInputStream(new FileInputStream(filePath));
int c=-1;
byte[] buffer=new byte[512];
while((c=bis.read(buffer))!=-1){
dos.write(buffer,0,c);
}
String answer=dis.readUTF();
System.out.println("服务器响应, "+answer);
……
发送文件名
发送文件数据
dos.write(-1);
FileServer.java
……
server=new ServerSocket(bindPort,20,serverAddr);
System.out.println("信息:服务器启动成功,开始监听 ");
session=server.accept();
DataInputStream dis=new DataInputStream(session.getInputStream());
DataOutputStream dos=new DataOutputStream(session.getOutputStream());
String fileName=dis.readUTF();
System.out.println("准备接收文件, "+fileName);
BufferedOutputStream bos=
new BufferedOutputStream(new FileOutputStream(new File(dir,fileName)));
int c=-1;
byte[] buffer=new byte[512];
while((c=dis.read(buffer))!=-1){
if(c==1 && buffer[0]==-1) break;
bos.write(buffer,0,c);
}
bos.close();
dos.writeUTF("文件接收成功 !");
System.out.println("信息:服务器发回响应,正常关闭 ");
……
接收文件名
int c=-1;
byte[] buffer=new byte[512];
while((c=dis.read(buffer))!=-1){
bos.write(buffer,0,c);
}
接收文件数据