java反射机制详解
2019-10-28 06:24:51来源:博客园 阅读 ()
java反射机制详解
一、什么是反射
JAVA反射机制是在运行状态中,对于任何一个类,都能够知道这个类的所有属性和方法;对于任何一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
获取字节码文件对象(获取class对象的方式)的三种方式:
1、根据类名:类名.class
2、根据对象:对象.getClass()
3、根据全限定类名:Class.forName(全限定类名)
二、通过反射机制获取信息
1、构造函数
//获取字节码文件 Class classs = Class.forName("com.zcbq.reflect.User"); //先获取有参构造,parameterTypes:表述参数列表,也可以不写 Constructor constructor = classs.getConstructor(int.class,String.class,int.class,String.class); //通过构造器来实例化对象,将实际的参数传进去 User user = (User) constructor.newInstance(01,"小轩",13,"打球");
获取全部构造函数:
//获取字节码文件 Class classs = Class.forName("com.zcbq.reflect.User"); //获取所有构造函数 Constructor constructor[] = classs.getConstructors(); //遍历所有构造函数 for(int i=0;i<constructor.length;i++){ //获取每个构造函数中的参数类型字节码对象 Class[] parameterTypes = constructor[i].getParameterTypes(); System.out.println("第"+i+"个构造函数:"); for (int j = 0; j < parameterTypes.length; j++) { System.out.println(parameterTypes[j].getName()+","); } }
console:
2、属性
在学习spring ioc之时,对未提供set方法的private属性依然可以注入感到神奇万分,现在看来,这神奇的根源自然是来自于java的反射,常用的方法如下:
2.1获取指定成员变量
//获取字节码文件 Class classs = Class.forName("com.zcbq.reflect.User"); //获取其实例对象 User user = (User) classs.newInstance(); //获取成员变量classs.getField(name);通过name来获取指定成员变量 //如果该成员变量是私有的,则应该使用getDeclaredField(name); Field declaredField = classs.getDeclaredField("userName"); //因为属性是私有的,获得其对象后,还要让打开可见权限 declaredField.setAccessible(true); //对成员变量进行操作 //赋值操作 declaredField.set(user, "Richard"); System.out.println(user.getUserName());
2.2获取全部属性
//获取字节码文件 Class classs = Class.forName("com.zcbq.reflect.User"); //获取其实例对象 User user = (User) classs.newInstance(); //赋值操作 user.setUserNum(01); user.setUserName("小轩"); //将私有属性一并获得 Field[] fields = classs.getDeclaredFields(); //遍历所有属性 for (int i = 0; i < fields.length; i++) { //打开可见权限 fields[i].setAccessible(true); System.out.println(fields[i].get(user)); }
3、方法
3.1不带参数的方法
//获取字节码文件 Class classs = Class.forName("com.zcbq.reflect.User"); //获取其实例对象 User user = (User) classs.newInstance(); //不带参数的方法,name为不带参数的方法 /* * classs.getMethod(name,paraMeterTypes) * name:方法的名称 * paraMeterTypes:方法的参数类型,没有则什么都不填 例如:String.class */ Method method = classs.getMethod("name"); //调用方法 /* * method.invoke(obj,args) * obj:方法的对象 * args:实际的参数值,没有则不填 */ method.invoke(user);
3.2带参数的方法
//获取字节码文件 Class classs = Class.forName("com.zcbq.reflect.User"); //获取其实例对象 // User user = (User) classs.newInstance(); //获取带参数的方法,为方法名 // Method method = classs.getDeclaredMethod("namess", String.class); //设置可见性 // method.setAccessible(true); //调用方法 // method.invoke(user, "text");
3.3获取所有的方法
//获取字节码文件 Class classs = Class.forName("com.zcbq.reflect.User"); //获取其实例对象 User user = (User) classs.newInstance(); //获取所有的方法 Method[] methods = classs.getMethods(); //遍历所有方法 for (Method method : methods) { //设置可见性 method.setAccessible(true); System.out.println(method.getName()); //获得方法的参数 Class<?>[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { //获得构造函数中参数类型 System.out.println(parameterTypes[i].getName()+","); } }
三、动态代理的概述及实现
1、动态代理概述
动态代理:利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象);
代理的是接口(Interfaces),不是类(Class),更不是抽象类。
2、动态代理的实现
分三步,但是注意JDK提供的代理正能针对接口做代理,也就是下面的第二步返回的必须要是一个接口。
2.1 new出代理对象,通过实现InvacationHandler接口,然后new出代理对象来。
2.2 通过Proxy类中的静态方法newProxyInstance,来将代理对象假装成那个被代理的对象,也就是如果叫人帮我们代买火车票一样,那个代理就假装成我们自己本人。
2.3 执行方法,代理成功
附属代码:
package com.zcbq.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHander implements InvocationHandler { private Object target; public MyInvocationHander() { super(); } public MyInvocationHander(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.err.println("开始"); method.invoke(target, args); //执行被代理的target对象的方法 System.out.println("结束"); return null; } }
附属代码:
Student student = new StuImp(); MyInvocationHander m = new MyInvocationHander(student); /** * student.getClass().getClassLoader():类加载器 * student.getClass().getInterfaces():被代理对象的接口 * m:代理对象 */ Student s = (Student) Proxy.newProxyInstance(student.getClass().getClassLoader(), student.getClass().getInterfaces(), m); s.login(); s.logout();
注意newProxyInstance的三个参数,第一个,类加载器,第二个被代理对象的接口,第三个代理对象。
原文链接:https://www.cnblogs.com/myRichard/p/11742194.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
- Java--反射(框架设计的灵魂)案例 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash