java基础之 反射

一、Class

1.Class是一个类。是对象照镜子后可以得到的信息:数据成员名、方法和构造器、某个类到底实现了哪些接口
2.对于每个类而言,JRE为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个类的有关信息
3.Class对象只能由系统建立
4.一个类在JVM中只有一个Class实例。每个类的实例都会记得自己是由哪个Class实例所生产

5.获取Class对象的方式

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Class clazz = null;  
  2. //1.通过类名.class获取  
  3. clazz = Person.class;  

  4. //2.通过对象的getClass()方法获取  
  5. Person person = new Person();  
  6. clazz = person.getClass();  

  7. //3.通过全类名获取  
  8. clazz = Class.forName("com.ithings.enumtest.Person");  
  9. //利用Class对象的newInstance方法来创建一个对象
  10. Objectobj = clazz.newInstance();

二、ClassLoader
     类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:

启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 

JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,

如下图所示


[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //1.获取系统类加载器 -- System ClassLoader  
  2.        ClassLoader classLoader = ClassLoader.getSystemClassLoader();  
  3.        //2.获取系统类加载器的父加载器扩展类加载器 -- Extension ClassLoader  
  4.        classLoader = classLoader.getParent();  
  5.        //3.获取扩展类加载器的父加载器系统类加载器 -- Bootstap ClassLoader(获取不到,为空)  
  6.        classLoader = classLoader.getParent();  
  7.        //4.测试当前类由哪个加载器加载 -- System ClassLoader  
  8.        classLoader = Class.forName("com.ithings.enumtest.PersonClass").getClassLoader();  
  9.        //5.测试JDK提供的Object对象由哪个加载器加载 -- Bootstap ClassLoader(获取不到,为空)  
  10.        classLoader = Class.forName("java.lang.Object").getClassLoader();  
  11.        //6.应用实例 -- 获取资源文件的输入流  
  12.        InputStream in = this.getClass().getClassLoader().getResourceAsStream("config.properties");  

 
三、Method对象
(一)获取

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Class clazz = Class.forName("com.ithings.enumtest.Person");  
  2.          
  3.        //1.获取所有方法,不包含private方法  
  4.        Method[] methods = clazz.getMethods();  
  5.          
  6.        //2.获取所有方法,包括private方法,且之获取当前类声明的方法  
  7.        methods = clazz.getDeclaredMethods();  
  8.          
  9.        //3.获取指定的方法  
  10.        Method method = clazz.getMethod("setName", String.class);  
  11.        method = clazz.getMethod("getName");  
  12.          
  13.        //4.执行方法 obj:执行哪个对象的方法,args:执行方法时需要传入的参数  
  14.        Object obj = clazz.newInstance();  
  15.        method.invoke(obj, "TT");  

(二)操作

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //5.工具方法 -- invoke  
  2. public void testClassMethod() throws Exception{  
  3.     //1.全类名  
  4.     String className = "com.ithings.enumtest.Person";  
  5.     //2.方法名:可能是父类方法,可能是私有方法  
  6.     String methodName = "setName";  
  7.     //3.参数列表  
  8.     Object[] args = {"AA"};  
  9.     invokeMethod(className, methodName, args);  
  10. }  
  11. //方法  
  12. public Object invokeMethod(String className, String methodName, Object ... args) throws Exception{  
  13.     //1.根据全类名,获取Class对象  
  14.     Class clazz = Class.forName(className);  
  15.       
  16.     //2.从给定的参数中,获取参数类型列表  
  17.     Class[] parameterTypes = new Class[args.length];  
  18.     for(int i=0; i<args.length;i++){  
  19.         parameterTypes[i] = args[i].getClass();  
  20.     }  
  21.       
  22.     //3.若当前类中无该方法,需要循环去父类中查找  
  23.     Method method = null;  
  24.     for(; clazz != Object.class; clazz = clazz.getSuperclass()){  
  25.         try{  
  26.             method = clazz.getDeclaredMethod(className, parameterTypes);  
  27.             break;  
  28.         }catch(Exception ex){  
  29.         }  
  30.     }  
  31.     //4.method可能是私有的,设置可访问私有方法  
  32.     method.setAccessible(true);  
  33.       
  34.     //5.method方法  
  35.     //5.1 创建类的对象  
  36.     Object obj = clazz.newInstance();  
  37.     //5.2 调用方法  
  38.     Object result = method.invoke(obj, args);  
  39.     return result;  
  40. }   

四、Field对象
(一)获取

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //1.全类名  
  2. String className = "com.ithings.enumtest.Person";  
  3. Class clazz = Class.forName(className);  
  4.   
  5. //1.获取Field的数组  
  6. Field[] fields = clazz.getDeclaredFields();  
  7.   
  8. //2.获取指定的Field  
  9. Field field = clazz.getDeclaredField("name");  
  10.   
  11. Person person = new Person("TT",3);  
  12. //3.1 获取指定对象的Field的值  
  13. Object val = field.get(person);  
  14. //3.2 设置指定对象的Field  
  15. field.set(person, "TT");  
  16.   
  17. //4. 若字段是私有的,则需要设置setAccessible  
  18. field.setAccessible(true);  


(二)操作

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public void testClassField() throws Exception{  
  2.     //1.全类名  
  3.     String className = "com.ithings.enumtest.Person";  
  4.     //2.方法名:可能是父类方法,可能是私有方法  
  5.     String fieldName = "";  
  6.     //3.属性值  
  7.     Object value = "TT";  
  8.     setField(className, fieldName, value);  
  9. }  
  10. //方法  
  11. public void setField(String className, String fieldName, Object value) throws Exception{  
  12.     //1.根据全类名,获取Class对象  
  13.     Class clazz = Class.forName(className);  
  14.       
  15.     //2.若当前类中无该属性,需要循环去父类中查找  
  16.     Field field = null;  
  17.     for(; clazz != Object.class; clazz = clazz.getSuperclass()){  
  18.         try{  
  19.             field = clazz.getDeclaredField(fieldName);  
  20.             break;  
  21.         }catch(Exception ex){  
  22.         }  
  23.     }  
  24.     //3.field,设置可访问私有方法  
  25.     field.setAccessible(true);  
  26.       
  27.     //4.设置field的值  
  28.     //5.1 创建类的对象  
  29.     Object obj = clazz.newInstance();  
  30.     //5.2 调用方法  
  31.     field.set(obj, value);  
  32. }   

五、动态代理
1.定义一个接口及实现类。定义一个被代理的对象,使用final修饰
2.类加载器通常是和被代理对象使用相同的类加载器
3.Proxy.newInstance()的返回值是一个被代理对象实现的接口的类型
4.InvocationHandler通常使用匿名内部类的方式
5.InvocationHandler的invoke()方法中的第一个参数Object类型的proxy指的是正在被返回的那个代理对象,一般不使用

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.    
  2. public void proxyMethod(){  
  3.     final IDoService doService = new DoServiceImpl();  
  4.     IDoService proxy = (IDoService)Proxy.newProxyInstance(doService.getClass().getClassLoader(),   
  5.             new Class[]{IDoService.class}, new InvocationHandler() {  
  6.         @Override  
  7.         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  8.             //方法执行前打印  
  9.             System.out.println("start with " + method.getName());  
  10.             //调用被代理的类的方法  
  11.             Object result = method.invoke(doService, args);  
  12.             //方法执行后打印  
  13.             System.out.println("end ");  
  14.             return null;  
  15.         }  
  16.     });  
  17.               
  18.     proxy.run("TT");  
  19.     proxy.walk("WH");  
  20. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值