1.java反射的概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。通俗的讲就是反射可以在运行时根据指定的类名获得类的信息。
2.反射的作用
首先我们先明确两个概念,静态编译和动态编译。
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。我们可以明确的看出动态编译的好处,而反射就是运用了动态编译创建对象。
在我们创建数据库链接时,这句代码Class tc = Class.forName("com.java.dbtest.TestConnection")就是告诉JVM去加载这个类,而加载的过程是在程序执行过程中动态加载的。通过类的全类名让jvm在服务器中找到并加载这个类,而如果是使用别的数据库,那就要换一个类了,如果是传统写死的方法创建,就要修改原来类的代码,而对于反射,则只是传入的参数就变成另一个了而已,可以通过修改配置文件,而不是直接修改代码。
在框架设计中常常用到反射机制,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类
简单来理解,使用反射能有效减低代码耦合。
3.反射的原理
JAVA语言编译之后会生成一个.class文件,反射就是通过字节码文件找到某一个类、类中的方法以及属性等,具体如何实现就先不管
4.反射的使用
直接上代码
package com.reflex;
/**
*
* 类名称: Student
* 类描述:
* 创建人: zzh
* 修改时间:2018年9月10日 下午2:40:12
* 修改备注:
* @version 1.0.0
*/
public class Student{
private int age;
public String name;
public Student(){}
public Student(String name,int age){
this.name=name;
this.age=age;
}
public String test1(){
return "test1";
}
public String test2(){
return "test2";
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
package com.reflex;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ClassReflexUtil {
private Class c;
public ClassReflexUtil() {
}
public ClassReflexUtil(String className) throws ClassNotFoundException {
//1.获取Class对象
c = Class.forName(className);
}
//获取构造函数的所有内容
private void getConstruction() {
System.out.println("************构造函数的所有内容(包括私有、受保护、默认的)********************");
Constructor[] constructors=c.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.print(Modifier.toString(constructor.getModifiers())+" ");//获取构造函数的修饰符
System.out.print(constructor.getName()+"("); //获取构造函数的名称
Class[] p=constructor.getParameterTypes();
for(int k=0;k<p.length;k++){
System.out.print(p[k].getName()+" ");
}
System.out.println(" );");
}
}
//获取相应类的所有属性
public void getParameter() throws ClassNotFoundException{
//获取属性
System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
Field[] fieldArray = c.getDeclaredFields();
for(Field f : fieldArray){
System.out.println(f);
}
/*
System.out.println("************获取所有公有的字段********************");
Field[] fieldArray = stuClass.getFi elds();
for(Field f : fieldArray){
System.out.println(f);
}*/
}
//获取相应类里面的所有申明的方法
private void getDeclaredFields() {
System.out.println("************获取所有的方法(包括私有、受保护、默认的)********************");
Method field[]=c.getDeclaredMethods();
for (Method method : field) {
System.out.print(Modifier.toString(method.getModifiers())+" "); //获取函数的修饰符权限
System.out.print(method.getReturnType()+" "+method.getName()+"("); //获取函数的名称
Class type[]= method.getParameterTypes();
for (Class aClass : type) {
System.out.print(aClass.getName()+" ");
}
System.out.println(");");
}
}
//设置相应类的属性值
public void setParameter(String parameter,String value) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException{
Field field=c.getField(parameter);
System.out.println(field);
//获取一个对象
Object obj = c.getConstructor().newInstance();
//为字段设置值
field.set(obj, value);
//验证
Student stu = (Student)obj;
System.out.println("验证姓名:" + stu.name);
}
public static void main(String[] args) throws Exception {
ClassReflexUtil cReflexUtil=new ClassReflexUtil("com.reflex.Student");
cReflexUtil.getParameter();
cReflexUtil.getConstruction();
cReflexUtil.getDeclaredFields();
}
}