zoukankan      html  css  js  c++  java
  • Java 中反射机制的深入研究

    昨天学习了java的反射机制,今天继续深入学习一下。

    一、通过反射操作数组

    反射不光只能用在类中,也可用在任意的引用数据类型上。当然包括数组。

    通过java.lang.reflect.Array 类 可操作数组,java.lang.reflect.Array 类 下面提供了很多方法。

    例如

    public static Object get(Object array,int index)throws IllegalArgumentException,ArrayIndexOutOfBoundsException //得到数组中的值

    下面演示如何操作

            Integer [] temp = {1,2,3};                               //声明一个数组
            Class<?> c1 = temp.getClass().getComponentType();        //取得数组的class对象        
            System.out.println(c1.getName());        
            System.out.println("数组中第一个元素的值: "+Array.get(temp,0)); //得到数组中第一个元素
            Array.set(temp, 0, 0);                        //改变数组中第一个元素
            System.out.println("数组中第一个元素的值: "+Array.get(temp,0));

    通过Array类操作temp这个数组。

    输出结果如下

    java.lang.Integer
    数组中第一个元素的值: 1
    数组中第一个元素的值: 0

    二、动态代理

    什么是代理设计

    这里讲一下什么是代理模式。

    代理模式的初衷就是,怎样才能在不直接操作对象的情况下,对对象进行访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 实际上在我的android项目 nju-wlan中对wifi的和gprs的控制就是用了代理模式。

     
    其实就是一个接口有两个子类。其中一个是真实的实现类,另外一个是代理类。

    请看代码

    package com.iip;
    
    
    interface People{              //接口
        public  void say(String name,int age);
    }
    
    class Chinas implements People{         //真实的实现类
    
        public Chinas(){        
        }    
        @Override
        public void say(String name, int age) {
            // TODO Auto-generated method stub
            System.out.println(name +  " " +age);
        }    
    }
    
    class ChinaProxy implements People{        //代理类
        People p = null;
        public ChinaProxy(People p) {
            // TODO Auto-generated constructor stub
            this.p = p;
        }
        @Override
        public void say(String name, int age) {
            // TODO Auto-generated method stub
            this.p.say(name, age);
        }    
    }
    
    public class Proxy {
        public static void main(String[] args ){
            People p = new ChinaProxy(new Chinas());
            p.say("lamport", 2013);
        }
        
    }

    看了这段代码,可能会想,那么这个代理有什么用呢?似乎看不到具体有什么好处啊!! 其实这样的主要好处是真正操作的类和接口实现的类并不存在联系,即减小了他们之间的耦合性。

    这种代理实际上称之为静态代理,因为一个代理类只为一个接口服务。

    如果有很多接口的话,每个接口都要有一个代理类。这样的话有很多重复。

    在java中要想实现动态代理机制。需要java.lang.reflect.InvocationHandler 和 java.lang.reflect.Proxy 类的支持。

    下面看 InvocationHandler接口,查看http://docs.oracle.com/javase/8/docs/api/ 文档下java.lang.reflect.InvocationHandler 这个接口中只要这一个抽象方法。

    public interface InvocationHandler { 

      Object invoke(Object proxy,Method method,Object[] args) throws Throwable

    }  

    参数说明:

    proxy :被代理的对象

    method:要调用的方法

    args:方法调用时所需要的参数

    可以将InvocationHandler的子类想象成一个代理的最终操作类。

    Proxy类是专门完成代理的操作类,可通过此类为一个或者多个接口动态的生成实现类。此类提供如下的操作方法,

    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException

    参数说明:

    ClassLoader :类的加载器       //如果想得到加载器的对象,肯定是用Class类来完成

    //写了一个Demo

    public class ClassLoaderDemo {
        public static void main(String[]args){
            Proxy p = new Proxy();
            System.out.println("类加载器:"+ p.getClass().getClassLoader().getClass().getName());
        }
    
    }

    输出为加载器的名字。

    输出:

    类加载器:sun.misc.Launcher$AppClassLoader

    Class<?>[] interfaces :得到全部的接口

    InvocationHandler h: 得到InvocationHandler 接口的子类实例

    直接上代码。

    package com.iip;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    interface People{
        public  void say(String name,int age);
    }
    
    class Chinas implements People{         //真实的实现类
    
        public Chinas(){        
        }    
        @Override
        public void say(String name, int age) {
            // TODO Auto-generated method stub
            System.out.println(name +  " " +age);
        }    
    }        
    
    class myInvocationgHandler implements InvocationHandler{        //使用动态代理
        
        private Object obj;
        
        public Object bind(Object obj){                                //绑定真实主题类
            this.obj = obj;                                            
            return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader()
                    , obj.getClass().getInterfaces(), this);        //取得代理对象
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) //动态调用方法
                throws Throwable {
            // TODO Auto-generated method stub
            Object object = method.invoke(this.obj, args);                    
            return object;
        }
        
    }
    
    public class Proxy {
        public static void main(String[] args ){
            People p = (People) new myInvocationgHandler().bind(new Chinas()); //绑定到动态代理中
            p.say("lamport", 2013);
        }
        
    }

    动态代理的好处,就是省去很多重复的代码。在spring中底层实现,也使用了动态代理。

    以上就是我今天的学习结果。最近想重新复习数据结构,由于很长时间没看过了,很多都忘了,有必要再复习下。树、图、搜索、遍历等等。

  • 相关阅读:
    微信授权,重定向两次
    Newtonsoft.Json 序列化 排除指定字段或只序列化指定字段
    各大快递公司面单号准确性验证的正则表达式,来自淘宝开放平台,时间是20181206,
    微信小程序web-view(webview) 嵌套H5页面 唤起微信支付的实现方案
    HTTP请求头及其作用 转
    sql server 只读帐号设置能读取存储过程,view等内容。
    PhantomJS命令行选项
    XML实体注入漏洞
    XmlDocument 避免XXE
    Centos7.6安装redis
  • 原文地址:https://www.cnblogs.com/maydayit/p/4232395.html
Copyright © 2011-2022 走看看