java反射机制详解
一、反射的概述
Java反射机制是 Java 语言的一个重要特性,它在服务器程序和中间件程序中得到了广泛运用。在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法。此外,在 ORM 中间件的实现中,运用 Java 反射机制可以读取任意一个 JavaBean 的所有属性,或者给这些属性赋值
反射就是把java类中的各种成分映射成一个个的Java对象
二,反射提供的功能
-
在运行时判断任意一个对象所属的类
-
在运行时构造任意一个类的对象
-
在运行时判断任意一个类所具有的成员变量和方法
-
在运行时调用任意一个对象的方法
class类 :代表一个类,是Java反射机制的起源和入口
要想实现反射,首先必须得到这个类的class字节码对象
用于获取与类相关的各种信息, 提供了获取类信息的相关方法
Class类继承自Object类
Class类是所有类的共同的图纸
每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。
三, 获取Class 对象的三种方法
想要操作反射,首先必须得到反射的入口
1.通过class.forName("全类名");
这里的全类名是包名点类名,仅仅写类名是找不到的。注意这里需要抛出异常
// 第一种
try {
Class<?> studentClass1 = Class.forName("exercise.Student");
}catch (ClassNotFoundException e ){
e.printStackTrace();
}
2.类名.class
Class<?> studentClass2 = Student.class;
3.对象.getClass()
Student stu1 = new Student("小明",1);
Class<?> studentClass3 = stu1.getClass();
四,根据class 对象获取类的信息
可以用一个类的反射入口class 对象获取类的所有信息
例1:获取此类的所有public 方法 ,其中包括,父类的,实现接口的,自己的
// 可以用一个类的反射入口class对象获取类的所有信息
// studentClass2 是我们利用上面三种方法之一 获取的class 对象
Method[] methods = studentClass2.getMethods();
for(Method method : methods ){
System.out.println(method);
}
例2:获取所有的构造方法
Constructor<?>[] constructors = studentClass2.getConstructors();
for(Constructor constructor : constructors ){
System.out.println(constructor);
}
例3: 获取父类
Class<?> superClass = studentClass2.getSuperclass();
例4: 获取当前类(只有本类的) 所有方法,包括私有的
Method[] declareMethods = studentClass2.getDeclaredMethods();
for(Method method : declareMethods ){
System.out.println(method);
}
例5: 获取当前类(只有本类的)所有属性,包括私有的
System.out.println("===========================================");
Field[] declareFields = studentClass2.getDeclaredFields();
for(Field field : declareFields){
System.out.println(field);
}
重点: 可以获取当前类的对象,并通过对象调用类的方法
try {
Object instance = studentClass2.newInstance();
Student student1 = (Student)instance;
student1.study();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
五,通过反射获取对象的实例 操作对象
-
class.newInstance() ,并强转类型,然后就可以操作对象了,主要是调用方法
Object instance = null;
try {
instance = studentClass2.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Student student2 = (Student)instance;
student2.setName("同济小孙");
student2.setId(1832921);
student2.study();
-
操作属性 可以操作类里面的public 属性和private 属性
如果属性是private ,正常情况下是不允许外界操作属性值,这里可以用Field 类的setAccessible(true) 方法,暂时打开操作的权限
System.out.println("===========================================");
try {
Student student3 =(Student)studentClass2.newInstance();
Field idField = studentClass2.getDeclaredField("id");
idField.setAccessible(true);
idField.set(student3,1111455);
System.out.println(student3.getId());
} catch (Exception e) {
e.printStackTrace();
}调用方法也一样,可以调用私有的方法,null 是因为这个方法没有参数
System.out.println("===========================================");
try {
Student student4 =(Student)studentClass2.newInstance();
Method sleepmethod = studentClass2.getMethod("sleep",null);
sleepmethod.setAccessible(true);
// 注意这个 sleep 方法需要是 public 修饰才可以访问到
sleepmethod.invoke(student4,null);
} catch (Exception e) {
e.printStackTrace();
}
六. 在程序执行中动态的决定调用的类以及方法
在本例中,程序执行之前,程序根本不知道具体的类和方法名是什么,需要执行时解析properties 文件,但是反射就可以办到
配置文件 :
文件名: class.txt
文件内容:
classnaem=reflect.Person
methodname=staticMethod
反射机制L
Properties prop = new Properties();
prop.load( new FileReader("class.txt"));
String className = prop.getProperty("classname");
String methodName = prop.getProperty("methodname");
Class<?> perClazz = null;
try{
perClazz = Class.forName(className);
}catch(ClassNotFoundExcepytion e ){
e.printStackTrace();
}
Method method = perClazz.getMethod(method);
method.invoke(perrClass.newInstance());
附录代码
public class Person {
private String name;
private int age;
public Person(String name,int age ){
this.name = name;
this.age = age;
}
}
public class Student extends Person {
private String name;
private int id;
public Student(String name ,int id ){
super(name,20);
this.name = name;
this.id = id ;
}
public Student (int id ){
super("无名氏",20);
this.name = "无名氏";
this.id = id;
}
public Student(){
super("无名无学号",20);
this.name = "无名无学号";
this.id = 100;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public void study(){
System.out.println(name +" , 学号为"+id + ", 正在认真的学习");
}
public void sleep(){
System.out.println(name +" , 学号为"+id + ", 正在睡觉");
}
}
测试
import exercise.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestReflect {
public static void main(String[] args ){
// 获取类对象的三种方式
// 第一种
try {
Class<?> studentClass1 = Class.forName("exercise.Student");
}catch (ClassNotFoundException e ){
e.printStackTrace();
}
// 第二种
Class<?> studentClass2 = Student.class;
// 第三种
Student stu1 = new Student("小明",1);
Class<?> studentClass3 = stu1.getClass();
// 可以用一个类的反射入口class对象获取类的所有信息
Method[] methods = studentClass2.getMethods();
for(Method method : methods ){
System.out.println(method);
}
System.out.println("===========================================");
Constructor<?>[] constructors = studentClass2.getConstructors();
for(Constructor constructor : constructors ){
System.out.println(constructor);
}
System.out.println("===========================================");
Class<?> superClass = studentClass2.getSuperclass();
System.out.println("===========================================");
Method[] declareMethods = studentClass2.getDeclaredMethods();
for(Method method : declareMethods ){
System.out.println(method);
}
System.out.println("===========================================");
Field[] declareFields = studentClass2.getDeclaredFields();
for(Field field : declareFields){
System.out.println(field);
}
System.out.println("===========================================");
try {
Object instance = studentClass2.newInstance();
Student student1 = (Student)instance;
student1.study();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("===========================================");
Object instance = null;
try {
instance =