本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188
反射和代理机制是JDK5.0提供的java新特性,反射的出现打破了java一些常规的规则,如,私有变量不可访问。但反射和代理在学习过程中也是一个比较难理解的知识点。本人曾经学过一段时间的反射和代理,但好长时间不用好像有点生疏了,当时学的时候就理解的不是很透彻,这次总结算是重新学习一遍吧,如果有什么错误,请大家拍砖:
先看一下,Java反射机制主要提供了以下功能:
•在运行时判断任意一个对象所属的类。
•在运行时构造任意一个类的对象。
•在运行时判断任意一个类所具有的成员变量和方法。
•在运行时调用任意一个对象的方法
一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(theabilityoftheprogramtoexamineitself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语
API简介
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
–Class类:代表一个类。
–Field类:代表类的成员变量(成员变量也称为类的属性)。
–Method类:代表类的方法。
–Constructor类:代表类的构造方法。
–Array类:提供了动态创建数组,以及访问数组的元素的静态方法
在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。
Class类是ReflectionAPI中的核心类,它有以下方法
–getName():获得类的完整名字。
–getFields():获得类的public类型的属性。
–getDeclaredFields():获得类的所有属性。
–getMethods():获得类的public类型的方法。
–getDeclaredMethods():获得类的所有方法。
-getMethod(Stringname,Class[]parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。
-getConstructors():获得类的public类型的构造方法。
•getConstructor(Class[]parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。
•newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
•(2)通过默认构造方法创建一个新对象:
•ObjectobjectCopy=classType.getConstructor(newClass[]{}).newInstance(newObject[]{});
•以上代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
•(3)获得对象的所有属性:
•Fieldfields[]=classType.getDeclaredFields();
•Class类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性
(4)Method类的invoke(Objectobj,Objectargs[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回
(5)Java中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class对象。要想使用反射,首先需要获得待处理类或对象所对应的Class对象。
获取某个类或某个对象所对应的Class对象的常用的3种方式:
a)使用Class类的静态方法forName:Class.forName(“java.lang.String”);
b)使用类的.class语法:String.class;
c)使用对象的getClass()方法:Strings=“aa”;Class<?>clazz=s.getClass();
下面写一个程序来用一下这些API吧:
注:1)处的int.class,int.class可以写为newClass[]{int.class,int.class}
原因在于getMethod方法的第二个参数是一个可变参数。
2)处的1,2可以写为newint【】{1,2},原因如1);
4.若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
a)先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:
Class<?>classType=String.class;
Objectobj=classType.newInstance();
b)先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?>classType=Customer.class;
Constructorcons=classType.getConstructor(newClass[]{});
Objectobj=cons.newInstance(newObject[]{});
注:
4.若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?>classType=Customer.class;
Constructorcons=classType.getConstructor(newClass[]{String.class,int.class});
Objectobj=cons.newInstance(newObject[]{“hello”,3});
代码示例:
5.Integer.TYPE返回的是int,而Integer.class返回的是Integer类所对应的Class对象。
java.lang.Array类提供了动态创建和访问数组元素的各种静态方法
一维数组的简单创建,设值,取值
Objectarray=Array.newInstance(classType,10);
Array.set(array,5,"hello");
Stringstr=(String)Array.get(array,5);
二维数组的简单创建,设值,取值
利用反射访问类的私有方法:
代码示例:
利用反射访问类的私有变量:
代理
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。
•在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
代理模式一般涉及到的角色有
–抽象角色:声明真实对象和代理对象的共同接口
–代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装
–真实角色:代理角色所代表的真实对象,是我们最终要引用的对象
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
•(1)InterfaceInvocationHandler:该接口中仅定义了一个方法
–publicobjectinvoke(Objectobj,Methodmethod,Object[]args)
•在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。
•(2)Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容
•protectedProxy(InvocationHandlerh):构造函数,用于给内部的h赋值。
•staticClassgetProxyClass(ClassLoaderloader,Class[]interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
•staticObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)
所谓DynamicProxy(动态代理)是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作
在使用动态代理类时,我们必须实现InvocationHandler接口
通过代理的方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系
动态代理是指客户通过代理类来调用其它对象的方法
•动态代理使用场合:
•调试
•远程方法调用(RMI)
动态代理的步骤:
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法
newProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)创建一个代理
4.通过代理调用方法
本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188
下一篇写:
相关推荐
JAVA程序员 从笨鸟到菜鸟
java程序员-从笨鸟到菜鸟.pdf
自学道路上的迷惑,所以从2012 年2 月份开始着手《java 程序员从笨鸟 到菜鸟》的编写。真心希望可以帮助刚起步学习java 开发的兄弟姐妹们。 没参与过中大型项目的开发,没有高的学历。所以此人之书只能供参考。
java程序员由菜鸟到笨鸟 作者:曹胜欢
java比较好的一篇文档,作者写的比较细,主要是一些基础概念说的比较细。
资源名称:《Java程序员-从笨鸟到菜鸟》PDF 下载资源目录:作者简介:..........................................................................................................................................
本电子书涵盖了从java基础到javaweb开放框架的大部分内容。在编写的过程中,难免会出现一些错误,希望大家能多多提些意见。
java程序员由菜鸟到笨鸟 一本值得java程序员看的书籍 给大家分享一下 喜欢的评个好评 谢谢
java程序员由菜鸟到笨鸟 作者:曹胜欢
java程序员由菜鸟到笨鸟 作者:曹胜欢
1.背景02. Netty 高性能之道0第 4 章第 4 章Java 数据库和网络Java 数据库和网络00Java 数据库操作0java 程序员从笨鸟到菜鸟之
摘要视图订阅曹胜欢欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章登录 | 注册Java程序员从笨鸟到菜鸟(81)学习专区