Java的反射机制
2016-04-23 22:50
381 查看
Java反射机制
1.反射机制提供的基本功能
在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法
2.反射机制需要了解的几点
实例化Class类对象运行时创建类对象并获取类的完整结构
通过反射调用类的指定方法、指定属性
动态代理
3.反射相关的主要API
java.lang.Class:代表类java.lang.reflect.Method:代表类的方法
java.lang.reflect.Filed:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造方法
4.反射方式与一般方式
一般方式引入需要的”包类”名称—>通过new实例化—>取得实例对象
反射方式
实例化对象—>getClass()方法—>得到完整的”包类”名称
如:普通类
class Person{ private String name; private int age; //get,set方法 //其他的方法 public void show(){ //代码 } public void display(String nation){ //代码 } public void SetAget(int age){ //代码 } public static void info(){ } //toString()方法 }
测试类:
正常方式:
//1.新建类的对象 Person person = new Person(); //2.通过类的对象调用属性方法 person.setAge(23); person.setName("Lucy"); person.show(); person.display("Ch");
反射方式:
//1.取得需要创建对象的类的Class类 Class<Person> clazz = Person.class; //2.创建clazz对应的运行时类Person类的对象,创建实例对象 Person person = clazz.newInstance(); //3.通过getDeclaredField(String str)获取类Person中定义的指定属性 Field fieldName = clazz.getDeclaredField("name"); Field fieldAge = clazz.getDeclaredField("age"); //4.设置属性可访问 fieldName.setAccessible(true); fieldAge.setAccessible(true); //5.通过方法set(Object obj, Object value)设置属性值 fieldName.set(person, "Lucy"); fieldAge.set(person, 25); //6.即可打印出设置的属性 System.out.println(person); //7.调用指定的类中定义的方法:getMethod(String name, Class<?>... parameterTypes);有参数时指定,无参数时可忽略 Method method = clazz.getMethod("show"); 或者 Method method = clazz.getMethod("display", String.class); //参数类型为方法形参的类型 Method method = clazz.getMethod("SetAge", int.class); //8.通过invoke(Object obj, Object... args);方法来调用Person中类的方法 method.invoke(person); //调用指定的方法,返回值类型为方法的返回类型 或者 method.invoke(person, "Ch"); //对于类中的静态方法调用 Method staticMethod = clazz.getMethod("info"); staticMethod.invoke(Person.class); //对于private声明的方法使用getDeclaredMethod()方法获取,并需要指定访问权限setAccessible(true);
每一个运行时类只加载一次,有Class的实例后,才可以:
①创建 对应的运行时类的对象;
②获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解…);
③调用对应的运行时类的指定结构(属性、方法、构造器)
5.获取Class实例的三种方式
调用运行时类本身的,class属性,如:Class clazz = Person.class; String str = clazz.getName();
通过运行时类的对象获取,如:
Person person = new Person(); Class clazz = person.getClass(); String name = clazz.getName();
通过Class的静态方法获取,如:
String className = "com.djh.java.Person"; //包名+类名 Class clazz = Class.forName(className); String name = clazz.getName();
如:类的加载器,在JDBC中会用到反射机制来获取驱动类的实例化对象
6.创建运行时类的对象
调用Class对象的newInstance()方法,newInstance调用的就是空参的构造器要求:类必须有一个无参数的构造器;
类的构造器的访问权限需要足够(不能设为private)
如:获取运行时类的对象
Class clazz = Person.class;
获取类的属性
getFields():只能获取运行时类”本身及其父类”中声明为public的所有属性,如:
Field[] fields = clazz.getFields(); for(int i = 0; i < fields.length; i++){ System.out.println(fields[i]); }
getDeclaredFields():获取运行时类”本身”声明的所有属性
Field[] fields = clazz.getDeclaredFields(); for(Field f : fields){ System.out.println(f.getName()); }
获取权限修饰符、变量类型、变量名
获取属性的权限修饰符
Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ //修饰符等级(public:1、private:2、protected:4、默认的为:0、static:8、final:10) int i = field.getModefiers(); //获取属性的权限修饰等级 String modify = Modefier.toString(i); //将修饰等级转化为对应的修饰字符 System.out.println(modify + " " + field.getName()); }
获取属性的变量类型、变量名
Class type = field.getType(); String name = field.getName();
获取运行时类的方法
getMethods():获取运行时类”本身及其父类”中所有声明为public的方法
Method[] methods = clazz.getMethods();
getDeclaredMethods():获取运行时类”本身”声明的所有方法
Method[] methods = clazz.getDeclaredMethods();
获取所有构造器
Constructor[] cons = clazz.getDeclaredConstructors(); for(Constructor con : cons){ System.out.println(con); //构造器方法设定可访问权限,setAccessible(true) con.setAccessible(true); //调用构造方法 Person person = coon.newInstance(); //可带参数 }
7.代理模块(动态代理)
每一个代理只能为一个接口服务通过代理类来调用其它对象的方法,并根据需要动态创建目标类的代理对象
代理设计(动态代理与静态代理比较)
静态代理
//1.需要先创建一个接口 interface ClothProduct{ void productCloth(); } //2.创建被代理类 class MyCloth implements ClothProduct{ @Override public void productCloth(){ } } //3.创建代理类 class ProxyClass implements ClothProduct{ //声明一个ClothProduct类型的引用 ClothProduct clothProduct; //创建代理类的构造器,完成对引用的初始化 //传入的参数clothProduct实际上是被代理类的对象 public ProxyClass(ClothProduct clothProduct){ this.clothProduct = clothProduct; } @Override public void productCloth(){ //代理类开始执行 clothProduct.productCloth(); } } public class TestProxy{ //创建被代理类对象 MyCloth myCloth = new MyCloth(); //创建代理类对象 ProxyClass proxyClass = new ProxyClass(myCloth); //代理类调用方法(发起对被代理的调用) proxyClass.clothProduct(); }
动态代理
//1.创建接口 interface SubInter{ void action(); } //2.创建被代理类 class ProxyedClass implements SubInter{ @Override public void action(){ //执行代码 } } //3.创建调用处理类(动态代理接口:InvocationHandler) class MyInvocationHandler implements InvocationHandler{ //实现接口的被代理的对象声明 Object obj; //创建方法:①给被代理类的对象实例化;②返回一个代理类的对象 public Object blind(Object obj){ this.obj = obj; //动态获取被代理类:obj.getClass().getClassLoader() //动态获取代理类实现的接口:obj.getClass().getInterfaces() //调用处理类对象:this(实现InvocationHandler接口的类对象) return Proxy.newProxyInsatce(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } //当通过代理类的对象发起对接口的被重写方法的调用时,都会转化为invoke()的调用 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ //val表示调用的方法的返回值 Object val = method.invoke(obj, args); return val; } } public void testProxy(){ //创建被代理类的对象 ProxyedClass pClss = new ProxyedClass(); //创建实现了InvocationHandler接口的类的对象 MyInvocationHandler mihandler = new MyInvocationHandler(); //动态创建代理类 Object obj = mihandler.blind(pClass); SubInter si = (SubInter)obj; //动态代理,通过接口InvocationHandler的实现类的invoke()方法调用 si.action(); }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树