java反射的核心理解.docx_第1页
java反射的核心理解.docx_第2页
java反射的核心理解.docx_第3页
java反射的核心理解.docx_第4页
java反射的核心理解.docx_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

反射:一切的操作都将使用Object完成如果已经有一个类,则肯定可以通过类创建对象;那么如果现在要求通过一个对象找一个类的名称,此时就需要用到反射机制了。publicfinalClassgetClass()返回类型是一个Class类,实际上此类是Java反射的源头。所谓反射从程序的运行结果来看也很好理解,即可以通过对象反射求出类的名称:如下:正常方式:引入需要的包.类名称-通过new实例化-取得实例化对象反射方式:实例化对象-getClass()方法-得到完整的”包.类“名称提示:所有类的对象实际上都是Class类的实例。在java中Object类是一切类的父类,那么所有类的对象实际上也就都是java.lang.Class类的实例所以所有的对象都可以转变为java.lang.Class类型表示Class本身表示一个类的本身,通过Class可以完整地得到一个类中的完整结构,包括此类中的方法定义和属性定义等。常用方法:1)publicstaticClassforName(StringclassName)throwsClassNotFoundException传入完整的“包.类”名称实例化Class对象2)publicConstructorgetConstructors()throwsSecurityException得到一个类中的全部构造方法3)publicFieldgetDeclaredFields()throwsSecurityException得到本类中单独定义的全部属性4)publicFieldgetFields()throwsSecurityException得到本类继承而来的全部属性5)publicMethod getMethods()throwsSecurityException得到一个类中的全部方法6)publicMethodgetMethod(Stringname,Class.parameterTypes)throwsNoSuchMethodException,SecurityException返回一个Method对象,并设置一个方法中的所有参数类型7)publicClassgetInterfaces()得到一个类中所有实现的全部接口8)publicStringgetName()得到一个类完整的包.类名称9)publicPackagegetPackage() 得到一个类的包10)publicClassgetSuperclass() 得到一个类的父类11)publicObjectnewInstance()throwsInstantiantionException,IllegalAccessException根据Class定义的类实例化对象12)publicClassgetComponentType()返回表示数组类型的Class13)publicbooleanisArray()判断此Class是否是一个数组Class类本身没有定义构造方法,所以如果要使用则首先必须通过forName()方法实例化对象,也可以使用“类.class”或“对象.getClass()”方法实例化调用有参数构造实例化对象:只有在操作时需要明确地调用类中的构造方法,并将参数传递进去之后才可以进行实例化操作:步骤:(1)通过Class类中的getConstructors()取得本类中的全部构造方法(2)向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数(3)之后通过Constructor实例化对象此处使用了Construtor类,表示构造方法。常用方法如下:publicintgetMedifiers() 得到构造方法的修饰符publicStringgetName() 得到构造方法的名称publicClassgetParameterType()得到构造方法中参数的类型pubicStringtoString()返回此构造方法的信息publicTnewInstance(Object.initrgs)throwsInstantiationException,IllegalAccessException,IllegalArgumentException,InvocationTargetException向构造方法中传递参数,实例化对象反射的应用-取得类的结构:在java.lang.reflect包中有以下几个类:Constructor:表示类中的构造方法Field:表示类中的属性Method:表示类中的方法这三个类都是AccessibleObject类的子类。取得所实现的全部接口要取得一个类所实现的全部接口,则必须使用Class类中的getInterfaces()方法.定义如下:publicClassgetInterface()getInterface()返回一个Class类的对象数组,之后直接利用Class类中的getName()方法输出即可取得父类:一具类可以实现多个接口,但是只能继承一个父类,所以如果要取得一个类的父类,可以直接使用Class类中的getSuperclass()方法。此方法定义如下:publicClassgetSuperclass()getSuperclass()返回的是Class实例,和之前得到一个接口一样,可以通过getName()方法取得名称取得全部方法使用Class类中的getMethods()方法,此方法返回一个Method类的对象数组。而如果要进一步取得方法的具体信息,则就必须依靠Method类,此类常用方法如下:A)publicintgetModifiers()取得本方法的访问修饰符B)publicStringgetName()取得方法的名称C)publicClassgetParameterTypes()得到方法的全部参数类型D)publicClassgetReturnType()得到方法的返回值类型E)publicClassgetExceptionTypes()得到一个方法的全部抛出异常F)publicObjectinvoke(Objectobj,Object.args)throwsIllegalAccessException,IllegalArgumentException,InvocationTargetExceiption通过反射调用类中的方法,此方法在后面将为读者介绍取得全部属性:两种不同的操作A).得到实现的接口或父类中的公共属性:publicFieldgetFields()throwsSecurityExceptionB).得到本类中的全部属性:publicFieldgetDeclaredFields()throwsSecurityException每个Field对象表示类中的一个属性,要取得属性的进一步信息,还需要Field类的常用方法如下:1)publicObjectget(Objectobj)throwsIllegalArgumentException,IllegalAccessException得到一个对象中属性的具体内容2)publicvoidset(Objectobj,Objectvalue)throwsIllegalArgumentException,IllegalAccessException设置指定对象中属性的具体内容3)publicintgetModifiers()得到属性的修饰符4)publicStringgetName()返回属性的名称5)publicbooleanisAccessible()判断此属性是否可被外部访问6)publicvoidsetAccessible(booleanflag)throwsSecurityException设置一个属性是否可以被外部访问7)publicstatcivoidsetAccessible(AccessibleObjectarray,booleanflag)throwsSecurityExceiption设置一组属性是否可被外部访问8)publicStringtoString()返回此Field类的信息通过反射调用类中的方法操作步骤如下:1)通过Class类的getMethod(Stringname,Class.parameterTypes)方法取得一个Method的对象,并设置此方法操作时所需要的参数类型2)之后才可以使用invoke进行调用,并方法中传递要设置的参数通过反射操作属性:在反射操作中虽然可以用Method调用类中的setter及getter方法设置和取得属性,但是这样操作毕竟很麻烦,所以在反射机制中也可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()就可以完成设置和取得属性内容的操作。但是在操作前需要注意的是,在类中的所有属性已经都设置成私有的访问权限,所以在使用set()或get()方法时首先要使用Field类中的setAccessible(true)方法将需要操作的属性设置成可以被外部访问。通过反射操作数组:反射机制不仅只能用在类上,还可以应用在任意的引用数据类型的数据上,当然,这本身就包含了数组,即可以使用反射操作数组。可以通过Class类的以下方法取得一个数组的Class对象publicClassgetComponentType()在反射操作包java.lang.reflect中使用Array类表示一个数组,可以通过此类取得数组长度,取得数组内容的操作。Array类常用方法如下:publicstaticObjectget(Objectarray,intindex)throwsIllegalArgumetnException,ArrayIndexOutOfBoundsException根据下标取得数组内容publicstaticObjectnewInstance(ClasscomponentType,intlength)throwsNegativeArraySizeException根据已有的数组类型开辟新的数组对象publicstaticvoidset(Objectarray,intindex,Objectvalue)throwsIllegalArgumentException,ArrayIndexOutOfBoundsException修改指定位置的内容7.Java反射java.lang.reflect1)反射是Java自我管理(类,对象)的机制2)*可以通过反射机制发现对象的类型发现类型的方法/属性/构造器3)*Java反射可以创建对象并访问任意对象方法和属性等4)Class加载类加载到内存:java将磁盘类文件加载到内存中,为一个对象(实例)这个对象是Class的实例,也就是这些对象都是Class实例5)Class实例代表Java中类型,基本类型的类型:int.class,long.class类类型Class实例获得如下:Classcls=String.class;Classcls=Class.forName(java.lang.String);Classcls=abc.getClass();以上方法获得cls是同一个对象,就是String类内存加载的结果 动态代理之前曾为读者讲解过代理机制的操作,但是所讲解的代理设计属于静态代理,因为每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理。最好的做法是可以通过一个代理类完成全部的代理功能,那么此时必须使用动态代理完成。在java中要想实现动态代理机制,则需要java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类的支持。InvocationHandler接口的定义如下:publicObjectinvoke(Objectproxy,Methodmethod,Objectargs)throwsThrowable在此接口中只定义了一个invoke()方法,此方法中有3个参数,意义如下:Objectproxy:被代理的对象Methodmethod:要调用的方法Objectargs:方法调用时所需要的参数Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类。Proxy类提供了如下的操作方法:publicstaticObjectnewProxyInstance(ClassLoaderloader,Classinterfaces,InvocationHandlerh)throwsIllegaArgumentException通过newProxyInstance()方法可以动态地生成实现类,此方法中的参数意义如下:ClassLoaderloader:类加载器Classinterfaces:得到全部的接口InvocationHandlerh:得到InvocationHandler接口的子类实例提示:类加载器在Proxy类的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在java中主要有以下3种类加载器。BootStrapClassLoader:此加载器采用C+编写,一般开发中是看不到的。ExtensionClassLoader:用来进行扩展类的加载,一般对应的是jrelibext目录中的类。AppClassLoader:加载classpath指定的类,是最常使用的一种加载器。装饰模式流的构造就是一个装饰模式的完整应用。节点流就像是一个最原始的元素,拥有有限的能力,过滤流就像是各种装饰元素,它们通过节点流来构造一个功能强大的流,如BufferedInputStream,DataInputStream.字节流与字符流之间的桥接器,对于输出流来说,它可以把字节流转变成字符流,(InputStreamReader)而对于输入流来说,它可以把字符流转换成字节流,(OutputStreamWriter);所以,用一个字节输入流来构造一个字符流如下:BufferedReaderbr=newBufferedReader(newInputStreamReader(newInputStream();如果想从键盘获得收入:可以这样封装一个BufferedReader;BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in);当然,对于“桥梁”,是可以指定字符编码方式的注:我们在多线程讲过,等待数据输入是会产生阻塞的。所以read()方法是会产生阻塞的。而对于BufferdReader中的readLine()方法,只有读到换行,它才会打破阻塞!一定要注意!现在,我们来介绍如何让一个对象持入化呢?实现一个接口:Serializable接口这是一个标记接口,不需要实现任何方法实现了Serializable接口的类的对象就可以序列化,注:如果此类中包含其它的类对象,则那个类也必需要实现Serializable接口。其实,序列化一个对象,就是序列化它所包含的属性。那么如何有先择地序列化其中某些属性,而某些属性是不序列化呢?关键字:transient它用来修饰实例变量表示此实例变量不被序列化。如:classStudentimplementsSeriailizableStringname;inttransientage;/在写对象时,age属性将不被序列化,在读到此属性时,它的值为0;注:Serializable接口不能自己定义序列化逻辑,它的子接口:Externalizable接口,它可以让你自己定义序列化对象的逻辑。详见API,这里不多做介绍小结:1.使用ObjectInputStream和ObjectOutputStream来读写对象2.对象必须要实现Serializable接口3.属性是对象,也要实现Serializable接口4.关键字transient来让属性不序列化5.用Externalizable来定义自己的序列化逻辑。类:RandomAccessFile它实现了DataInput,DataOutput接口;可读/可写此类可以访问一个文件中的随机位置(并不一定是从头到尾)方法:getFilePoint()/获得此文件中的当前偏移量seek(longpos);/定位当前指针的偏移量read(),read(bytebuf),read(bytebuf,intoff,intlen);write(intb),write(bytebuf),write(bytebuf,intoff,intlen);(一)ObjectInputStream对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化。ObjectOutputStream和ObjectInputStream分别与FileOutputStream和FileInputStream一起使用时,可以为应用程序提供对对象图形的持久存储。只有支持java.io.Serializable或java.io.Externalizable接口的对象才能从流读取。readObject方法用于从流读取对象。应该使用Java的安全强制转换来获取所需的类型。在Java中,字符串和数组都是对象,所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。可以使用DataInput上的适当方法从流读取基本数据类型。例如,要从由ObjectOutputStream中的示例写入的流读取:FileInputStreamfis=newFileInputStream(t.tmp);ObjectInputStreamois=newObjectInputStream(fis);inti=ois.readInt();Stringtoday=(String)ois.readObject();Datedate=(Date)ois.r

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论