简单生活 趣味人生
  最后的告别 最后一个心愿是学会高飞

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中底层实现,也使用了动态代理。

 

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

 

posted @ 2015-01-18 21:40  MayDayIT  阅读(232)  评论(0编辑  收藏  举报