java反射机制详解_JAVA中的反射机制详解
JAVA中的类反射就是⼀个在当前JVM中⽀持类、接⼝和对象内省的⼩型的,类型安全的和可靠的API。它是通过flect包提供的,可以对类的能⼒进⾏分析。反射使程序代码能够访问装载到JVM中的类的内部信息。主要包括获取已装载类的字段、⽅法和构造函数的信息。允许编写处理类的代码.这些类是在程序运⾏时临时确定的,⽽⾮源代码中事先选定的。这使反射成为构建灵活的应⽤的主要⼯具。
“Class”类 JAVA中的“Class”类是JAVA中⼀个⼗分特殊的类。它和其它类 ⼀样继承⾃“Object”类,其对象⽤以表达JAVA程序运⾏时的类和 接⼝。当⼀个类被加载时,JVM便⾃动产⽣⼀个类对象。 “Class”是JAVA反射机制的起源。针对任何想探查的类。只有 先为它产⽣⼀个“Class”对象.接下来才能由这个“Class”对象调⽤ 为数⼗多个的反射APIs。因此。利⽤反射APIs动态访问某个类要 经过以下三个步骤:
1创建⼀个“Class”对象:
2利⽤创建的“Class”对象获
3利⽤flect包中提供的反射APIs,动态处理上⼀步获得的类的内部信息。
获取“Class”对象
类的内部信息与反射APIs的对应关系:
通过获取的“Class”对象就可以动态获取类的内部信息。类内部信息与反射APIs的对应关系如表所⽰
利⽤反射实现SQL语句的动态⽣成
在JSP技术中,利⽤From表单元素与JavaBean属性(成员变量)的对应关系,并符合⼀定的命名规范,就可以设计数据库所需 ⼀稍SQL语句。但在使⽤的过程中,发现⼀个问题。这样的SQL语 句不能灵活⽣成,随着JSP页⾯的增加,每⼀个JavaBean都要做 这种重复的⼯作。使得代码量增⼤,软件构件问的耦合性增加,不 利于软件构件的重⽤。所以有必要寻求⼀种较为通⽤技术来解决 这个问题。 JAva的反射技术就提供了这样⼀种可能。现在以查询语句为 例.利⽤反射技术动态⽣成SQL语句。在JavaBean类中的属性对 应JSP页⾯中表单的每个元素,同时对应查询的数据库中表的相 应字段。 下⾯实例程序中,getFileds⽅法可以获取⼀个JavaBean实例 中的每个属性,⽅法的参数是这个JavaBean类的实例;constructs-elect ⽅法可以获得动态⽣成的Select语句,⽅法的参数是这个 JavaBean 类的实例、要查询的数据库表名称和查询条件(可以为 空)。
⼆、什么是Java中的类反射:
Reflection 是 Java 程序开发语⾔的特征之⼀,它允许运⾏中的 Java 程序对⾃⾝进⾏检查,或者说“⾃审”,并能直接操作程序的内部属性和⽅法。Java 的这⼀能⼒在实际应⽤中⽤得不是很多,但是在其它的程序设计语⾔中根本就不存在这⼀特性。例如,Pascal、C 或者
C++ 中就没有办法在程序中获得函数定义相关的信息。
Reflection 是 Java 被视为动态(或准动态)语⾔的关键,允许程序于执⾏期 Reflection APIs 取得任何已知名称之 class 的內部信息,包括package、type parameters、superclass、implemented interfaces、inner classes, outer class, fields、constructors、methods、modifiers,並可于执⾏期⽣成instances、变更 fields 內容或唤起 methods。
三、Java类反射中所必须的类:
Java的类反射所需要的类并不多,它们分别是:Field、Constructor、Method、Class、Object,下⾯我将对这些类做⼀个简单的说明。
Field类:提供有关类或接⼝的属性的信息,以及对它的动态访问权限。反射的字段可能是⼀个类(静态)属性或实例属性,简单的理解可以把它看成⼀个封装反射类的属性的类。
Constructor类:提供关于类的单个构造⽅法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,⽽Constructor类则封装了反射类的构造⽅法。
Method类:提供关于类或接⼝上单独某个⽅法的信息。所反映的⽅法可能是类⽅法或实例⽅法(包括抽象⽅法)。 这个类不难理解,它是⽤来封装反射类⽅法的⼀个类。
Class类:类的实例表⽰正在运⾏的 Java 应⽤程序中的类和接⼝。枚举是⼀种类,注释是⼀种接⼝。
每个数组属于被映射为 Class 对象的⼀个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
Object类:每个类都使⽤ Object 作为超类。所有对象(包括数组)都实现这个类的⽅法。
四、Java的反射类能做什么:
看完上⾯的这么多我想你已经不耐烦了,你以为我在浪费你的时间,那么好吧!下⾯我们就⽤⼀些简单的⼩例⼦来说明它。
⾸先我们来看⼀下通过Java的反射机制我们能得到些什么。
⾸先我们来写⼀个类:
java 代码
importjava.awt.event.ActionListener;
importjava.awt.event.ActionEvent;
classAextendsObjectimplementsActionListener{
privateinta =3;
publicInteger b =newInteger(4);
publicA(){}
publicA(intid,String name){}
publicintabc(intid,String name){return0;}
publicvoidactionPerformed(ActionEvent e){}
}
你可能被我这个类弄糊涂了,你看不出我要做什么,那就不要看这个类了,这个类是⽤来测试的,你知道知道它继承了Object类,有⼀个接⼝是ActionListener,两个属性int和Integer,两个构造⽅法和两个⽅法,这就⾜够了。
下⾯我们把A这个类作为⼀个反射类,来过去A类中的⼀些信息,⾸先我们先来过去⼀下反射类中的属性和属性值。
java 代码
flect.*;
classB{
publicstaticvoidmain(String args[]){
A r = newA();
Class temp = r.getClass();
try{
System.out.println("反射类中所有公有的属性");
Field[] fb =Fields();
for(intj=0;j
Class cl = fb[j].getType();
System.out.println("fb:"+cl);
}
System.out.println("反射类中所有的属性");
Field[] fa = DeclaredFields();
for(intj=0;j
Class cl = fa[j].getType();
System.out.println("fa:"+cl);
}
System.out.println("反射类中私有属性的值");
Field f = DeclaredField("a");
f.setAccessible(true);
Integer i = ((r);
System.out.println(i);
}catch(Exception e){
e.printStackTrace();
}
}
}
这⾥⽤到了两个⽅法,getFields()、getDeclaredFields(),它们分别是⽤来获取反射类中所有公有属性和反射类中所有的属性的⽅法。另外还有getField(String)和getDeclaredField(String)⽅法都是⽤来过去反射类中指定的属性的⽅法,要注意的是getField⽅法只能取到反射类中公有的属性,⽽getDeclaredField⽅法都能取到。
这⾥还⽤到了Field 类的setAccessible⽅法,它是⽤来设置是否有权限访问反射类中的私有属性的,只
有设置为true时才可以访问,默认为false。另外 Field类还有set(Object AttributeName,Object value)⽅法,可以改变指定属性的值。
下⾯我们来看⼀下如何获取反射类中的构造⽅法
java 代码
flect.*;
javabean是干什么的publicclassSampleConstructor {
publicstaticvoidmain(String[] args) {
A r = newA();
printConstructors(r);
}
publicstaticvoidprintConstructors(A r) {
Class c = r.getClass();
//获取指定类的类名
String className = c.getName();
try{
//获取指定类的构造⽅法
Constructor[] theConstructors = c.getConstructors();
for(inti=0; i
//获取指定构造⽅法的参数的集合
Class[] parameterTypes = theConstructors[i].getParameterTypes();
System.out.print(className + "(");
for(intj=0; j
System.out.print(parameterTypes[j].getName() + " ");
System.out.println(")");
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
这个例⼦很简单,只是⽤getConstructors()⽅法获取了反射类的构造⽅法的集合,并⽤Constructor类的getParameterTypes()获取该构造⽅法的参数。
下⾯我们再来获取⼀下反射类的⽗类(超类)和接⼝
java 代码
importjava.io.*;
flect.*;
publicclassSampleInterface {
publicstaticvoidmain(String[] args)throwsException {
A raf = newA();
printInterfaceNames(raf);
}
publicstaticvoidprintInterfaceNames(Object o) {
Class c = o.getClass();
//获取反射类的接⼝
Class[] theInterfaces = c.getInterfaces();
for(inti=0; i
System.out.println(theInterfaces[i].getName());
//获取反射类的⽗类(超类)
Class theSuperclass = c.getSuperclass();
System.out.Name());
}
}
这个例⼦也很简单,只是⽤Class类的getInterfaces()⽅法获取反射类的所有接⼝,由于接⼝可以有多个,所以它返回⼀个 Class数组。⽤getSuperclass()⽅法来获取反射类的⽗类(超类),由于⼀个类只能继承⾃⼀个类,所以它返回⼀个Class对象。
下⾯我们来获取⼀下反射类的⽅法
java 代码
flect.*;
publicclassSampleMethod {
publicstaticvoidmain(String[] args) {
A p = newA();
printMethods(p);
}
publicstaticvoidprintMethods(Object o) {
Class c = o.getClass();
String className = c.getName();
Method[] m = c.getMethods();
for(inti=0; i
//输出⽅法的返回类型
System.out.print(m[i].getReturnType().getName());
//输出⽅法名
System.out.print(" "+m[i].getName()+"(");
//获取⽅法的参数
Class[] parameterTypes = m[i].getParameterTypes();
for(intj=0; j
System.out.print(parameterTypes[j].getName());
if(parameterTypes.length>j+1){
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论