java的反射机制学习和理解
一、反射
反射即是通过类名字符串获取类的信息的过程。
任何类的字节码(或类模板)都是Class类的一个对象,或者说Class类是所有类的元类。
二、反射的准备
1、获取类的字节码
Class cl1 = Class.forName("ClassName");//通过类名获取类的字节码
Class cl2 = ClassName.class;// 通过类名获取类的字节码
Class cl3 = objectOfCalss.getClass(); //通过对象获取类的字节码
以上三种方法获取的类的字节码为同一个对象,在使用上并无任何差别,只在使用的情景和先决条件上有所不同。
2、获取构造函数
Construstor con = cl1.getConstrustor() ;
//通过类的字节码(元类对象)调用getConstrustor方法,默认获得无参构造器
Construstor con1 = cl1.getConstrustor(int.class,String.class) ;
//获取带int类型、string类型的构造器,传递参数类型为元类对象,编译阶段无法判断是否存在该构造器
Construstor[] cons = cl1.getConstrustors() ;
//获取该类的所有构造器,其在数组中存放的顺序不保证,不建议使用下标访问
Object obj = con.newInstance();//调用构造器的newInstance方法创建类的实例对象,返回值为object类型
ClassName cn = (ClassName)con1.newInstance(1,"aa");//调用带参构造器创建对象,并进行类型转换
由元类对象使用getConstructor()方法获得该类的构造函数,默认返回无参构造器,可以传递元类对象型参数(.class)来指定获得某个构造器,返回为一个constructor对象。
使用getConstructors()方法获得所有构造函数,返回一个constructor对象数组。
constructor对象调用newInstance()方法创建实例对象,返回object对象,需要自己根据类型进行转换。
3、获取属性对象
Field fi1 = cl1.getField("id");//获得名为id的公有属性对象
Field[] fis1 = cl1.getFields();//获得该类所有公有属性对象,包括继承自父类的属性对象
Field fi2 = cl1.getDeclareField("id");//获得名为id的属性对象,
Field[] fis2 = cl1.getDeclareFields();//获得该类所有属性对象,包括继承自父类的属性对象
获取属性对象有四种方法,getField(String)、getFields()、getDeclareField(String)、getDeclareFields(),前两者只能获取公有属性对象,后两者可以获得所有的属性对象。返回为Field对象和Field对象数组。
4、 获取方法对象
Method me1 = cl1.getMethod("run");//获得名为run的不带参数的公有方法对象,
Method[] me1 = cl1.getMethods();//获得该类所有公有方法对象,包括继承自父类的方法
Method me2 = cl1.getDeclareMethod("run",int.class,String.class);//获得名为run的方法对象,参数为(int,String)
Method[] me2 = cl1.getDeclareMethods();//获得该类所有方法对象,包括继承自父类的方法
获取方法对象的方法同样有四种,类似于获取属性对象,获取重载方法的方式类似于获取构造器,需传入元类对象作为参数进行匹配。
三、反射的使用
1、Field类的方法
fi1.get(object);//获得object对象的fi1属性的值
//fi1属性对象和object对象在操作前就已经获得
fi1.set(object,111);//给object对象的fi1属性赋值为111
//为属性赋值的类型必须对应
fi2.setAccessable(true);//设置该属性的私有属性的可访问性,true为可访问
//若该属性本身非私有属性则该操作无效,即本身就是可访问的
2、Method类的方法
me1.invoke(object,ars...);//调用object的me1方法,传递参数为该方法实际需要的参数
//object对象和方法对象均提前获得
me2.setAccessable(true);//设置该属性的私有方法的可访问性,true为可访问
//若该方法本身非私有属性则该操作无效,即本身就是可访问的
小结
我们正常情况下是通过对象来访问他的属性和方法,而反射提供了获取类的属性和方法的途径,通过属性对象和方法对象来对对象的属性和方法进行操作和调用,以满足一些特殊情况下的使用。