当前位置: 首页 > news >正文

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

 

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

 

转载于:https://www.cnblogs.com/maydayit/p/4232395.html

相关文章:

  • 从头开始学JavaScript (十二)——Array类型
  • FrameLayout的作用
  • 解决git push远程分支错误
  • Ubuntu 终端命令整理
  • 算法模板——线段树5(区间开根+区间求和)
  • 在Apache下开启SSI配置
  • PHP 文件上传功能
  • Ngnice-国内ng学习网站
  • 【Java】使用动态代理与包装模式实现连接池
  • 关于exp/imp的总结学习
  • Flash中动态生成Js方法,实现页面刷新等功能
  • UITextView的使用详解
  • C#操作Xml:XSLT语法 在.net中使用XSLT转换xml文档示例
  • [SAP ABAP开发技术总结]面向对象OO
  • Java内存模型(二)
  • 【391天】每日项目总结系列128(2018.03.03)
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 【知识碎片】第三方登录弹窗效果
  • Consul Config 使用Git做版本控制的实现
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • ES6--对象的扩展
  • gf框架之分页模块(五) - 自定义分页
  • HashMap剖析之内部结构
  • interface和setter,getter
  • Java超时控制的实现
  • java取消线程实例
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • MySQL用户中的%到底包不包括localhost?
  • python学习笔记-类对象的信息
  • React-生命周期杂记
  • TypeScript迭代器
  • vue-loader 源码解析系列之 selector
  • 闭包--闭包之tab栏切换(四)
  • 关于使用markdown的方法(引自CSDN教程)
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 区块链技术特点之去中心化特性
  • 山寨一个 Promise
  • 算法---两个栈实现一个队列
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 我与Jetbrains的这些年
  • 湖北分布式智能数据采集方法有哪些?
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • #pragma multi_compile #pragma shader_feature
  • #控制台大学课堂点名问题_课堂随机点名
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)平衡树
  • (转)重识new