反射 Reflection
本文参考文章:
引入
动态编程语言:程序运行时,允许改变程序结构或变量类型
从这个概念来看,Java不属于动态编程语言之类
Java的一个突出的动态相关机制:Reflection
反射概念
运行状态中
- 对于任意一个类,都能知道其所有属性和方法
- 对于任意一个对象,都能够调用其任意一个方法
Java反射功能
类 对象 动态代理
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
- 生成动态代理
Java反射机制的原理
Java内存区域划分
(下方表格中未全部列出)
堆区 | 栈区 | 方法区(静态区) |
---|---|---|
存放类的对象。JVM将所有对象的实例的内存都分配在堆上,在堆中分配内存时间较长 | 存取速度快,栈中存放的都是快速执行的任务,如基本数据类型的数据,对象的引用 | 存放类、静态变量(static变量)、静态方法、常量、成员方法 |
jvm装载某类型时,装载器会定位相应的class文件,然后将其读入到虚拟机中,并提取class中的类型信息,信息存储到方法区中
Java反射机制中涉及的类
Class
类的实例表示正在运行的Java应用程序中的类和接口
Field
提供有关类或接口的属性信息,以及对其的动态访问权限
Constructor
提供关于类的单个构造方法的信息以及对其的访问权限
Method
提供关于类或接口上单独某个方法的信息
特殊:Class类
Class的实例用以表达Java程序运行时的类和接口
获取Class对象
- Object.getClass()
- Class.getSuperClass()
- Class.forName()
- 包装器类型:类名.TYPE属性
反射机制应用
- 操作数据库:动态创建SQL语句
- 解析XML:解析XML动态生成对象
- 动态代理
- 在框架中的应用:Struts、Spring、Hibernate
缺点
对性能的影响:使用反射基本上是一种解释操作,这种操作总是慢于直接执行相同的操作
代码示例
Person.class
public class Person {
private String name;
private Integer age;
private List<String> hobbies;
public Person() {
}
public Person(String name, Integer age, List<String> hobbies) {
this.name = name;
this.age = age;
this.hobbies = hobbies;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
}
Student
public class Student extends Person implements Serializable{
private String schoolName;
private String stuNo;
public Student(){
}
public Student(String schoolName, String stuNo) {
this.schoolName = schoolName;
this.stuNo = stuNo;
}
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
}
Test.Class
public class Test {
/**
* 反射测试
* @param args
*/
public static void main(String[] args) throws ClassNotFoundException {
Student student = new Student();
Class<? extends Student> stuClass = student.getClass();
System.out.println("获取student的Class");
System.out.println("student的Class:"+stuClass+"\n");
System.out.println("stuClass的构造方法" + Arrays.toString(stuClass.getConstructors()));
Class<?> superclass = stuClass.getSuperclass();
Class<?>[] interfaces = stuClass.getInterfaces();
System.out.println("继承的类:"+superclass);
System.out.println("实现的接口:" + Arrays.toString(interfaces));
System.out.println();
// 获取Student中声明的方法
Method[] declaredMethods = stuClass.getDeclaredMethods();
System.out.println("Student对象声明的可用方法:");
for (Method method:declaredMethods){
System.out.print(" 方法名称:" + method.getName());
System.out.print(" 方法参数:" + Arrays.toString(method.getParameterTypes()));
System.out.println(" 方法返回类型:" + method.getReturnType());
}
// 获取Student可用的所有方法
Method[] methods = stuClass.getMethods();
System.out.println("Student对象所有可用方法:");
for (Method method:methods){
System.out.print(" 方法名称:" + method.getName());
System.out.print(" 方法参数:" + Arrays.toString(method.getParameterTypes()));
System.out.println(" 方法返回类型:" + method.getReturnType());
}
}
}
执行结果
获取student的Class
student的Class:class com.reflect.entity.Student
stuClass的构造方法[public com.reflect.entity.Student(), public com.reflect.entity.Student(java.lang.String,java.lang.String)]
继承的类:class com.reflect.entity.Person
实现的接口:[interface java.io.Serializable]
Student对象声明的可用方法:
方法名称:setStuNo 方法参数:[class java.lang.String] 方法返回类型:void
方法名称:setSchoolName 方法参数:[class java.lang.String] 方法返回类型:void
方法名称:getSchoolName 方法参数:[] 方法返回类型:class java.lang.String
方法名称:getStuNo 方法参数:[] 方法返回类型:class java.lang.String
Student对象所有可用方法:
方法名称:setStuNo 方法参数:[class java.lang.String] 方法返回类型:void
方法名称:setSchoolName 方法参数:[class java.lang.String] 方法返回类型:void
方法名称:getSchoolName 方法参数:[] 方法返回类型:class java.lang.String
方法名称:getStuNo 方法参数:[] 方法返回类型:class java.lang.String
方法名称:getName 方法参数:[] 方法返回类型:class java.lang.String
方法名称:setName 方法参数:[class java.lang.String] 方法返回类型:void
方法名称:setAge 方法参数:[class java.lang.Integer] 方法返回类型:void
方法名称:getHobbies 方法参数:[] 方法返回类型:interface java.util.List
方法名称:setHobbies 方法参数:[interface java.util.List] 方法返回类型:void
方法名称:getAge 方法参数:[] 方法返回类型:class java.lang.Integer
方法名称:wait 方法参数:[] 方法返回类型:void
方法名称:wait 方法参数:[long, int] 方法返回类型:void
方法名称:wait 方法参数:[long] 方法返回类型:void
方法名称:equals 方法参数:[class java.lang.Object] 方法返回类型:boolean
方法名称:toString 方法参数:[] 方法返回类型:class java.lang.String
方法名称:hashCode 方法参数:[] 方法返回类型:int
方法名称:getClass 方法参数:[] 方法返回类型:class java.lang.Class
方法名称:notify 方法参数:[] 方法返回类型:void
方法名称:notifyAll 方法参数:[] 方法返回类型:void