Java反射入门
Java为我们提供了反射机制,反射——在生物中被这样解释:动物通过中枢神经系统对刺激的一种应答式反应,在物理中它被这样解释:声波、光波或其他电磁波遇到障碍物或别种媒质面而折回,那么它在Java中又该怎么解释呢?首先我们来看看它能做什么:
1. 在运行时判断任意一个实例的所属类。
2. 在运行时构造任意一个类的实例。
3. 在运行时获取任意类所具有的属性和方法。
4. 在运行时调用任意对象的方法。
不知道大家有没有注意到“运行时”这三个字,它能让我们的程序更加动态,更加的灵活,好了,废话少说,我们一个一个来实现上面所说的功能。
在解决以上问题之前,我们先看看java为我们提供了哪些类来实现反射:
Class:它代表一个类,JVM每加载一个类都会实例一个相应的Class对象,如何取得它我们后话再讲。
Field:它代表类的属性。
Method:它代表类的方法。
Constructor:它代表类的构造方法。
1.在运行时判断任意一个实例的所属类。
首先我们准备一个用于测试的Javabean:
package vo;
public class UserVo {
private String name;
public UserVo(){}
public String getName(){
return this.name;
}
public void setName(String name){
this.name=name;
}
}
我们将围绕这个类来进行测试。我们再写一个类名叫:TestReflection,代码如下:
package reflection;
import vo.UserVo;
public class TestReflection {
/**
* 打印类的信息
*/
public void refClassInfo(Object o){
Class c=o.getClass();
System.out.println(c.getName());
}
public static void main(String[] args) {
UserVo t=new UserVo();
new TestReflection().refClassInfo(t);
}
}
现执行下看看效果,是不是动态的获取了类名?接着我们来看看它的实现。
public void refClassInfo(Object o){
Class c=o.getClass();
System.out.println(c.getName());
}
主要就是这个方法了,它有一个Object型的参数,在执行它之前我们并不知道它是属于那个类的,但程序运行时我们就可以通过Class.getName()这个方法来得到。
前面我们说过Class代表一个类,我们在这个例子中,通过调用对象的getClass(),来获取此对象的Class对象,既然它代表类,那么它肯定拥有这个类的所有信息,getName()这个方法就能获得它的类名。
后面的一切操作都是以它为基础的,在java中如果要反射,我们就得现获得Class对象,这个道理很简单,如果你连哪个类都不知道,你怎么去找它的方法?呵呵。
2.在运行时构造任意一个类的实例。
在这个例子中,假设我们知道类名,但没有这个对象,我们通过反射机制来动态的获取一个对象。
public static Object getInstance(String className){
try {
Class c=Class.forName(className);
return c.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
这个例子中,我们接触一种新的获取Class的方法,通过Class.forName(String className)这个方法,得到Class对象后,再调用它的newInstance()即可获得此类的对象。
我们怎么调用这个方法呢?
public static void main(String[] args) {
UserVo t=(UserVo)TestReflection.getInstance("vo.UserVo");
}
上面我们确实获取了实例,但这种方法有个缺点,就是只支持无参的构造函数,如果我们要实例的类它的构造函数是有参的我们该怎么办,这里我们要用到Constructor类,还记得它吗?前面说过它代表构造方法,我们来看代码。
public static Object constructInstance(String className){
try {
Class c=Class.forName(className);
Class[] paramList={String.class};//参数列表
Constructor ctor=c.getConstructor(paramList);
Object[] param={"hello"};
return ctor.newInstance(param);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
首先我先介绍下String.class这个写法,这种方法也可以获取某类的Class对象,这里获取的String的Class对象,至此我们学习三种获取Class的方法。
1. Object.getClass();
2. Class.forName(className);
3. new Object().class;
——接下来我们继续分析代码。
构造好参数列表(形参)后,我们可以通过这个这个参数列表来找一个构造方法:
Constructor ctor=c.getConstructor(paramList);
Class类的getConstructor()方法可以获取指定参数列表的构造方法类:Constructor,Constructor类同样有一个newInstance()的方法,只不过这次得传参数了,这里必须传Object的数组,但我们构造方法的参数是String型的怎么办?根据多态的特性,我们知道父类的引用可以指向子类的对象,这里我们只需在Object数组中放入String的对象就OK了。
Object[] param={"hello"};
最后调用ctor.newInstance(param);获得该对象的实例。
要使用本函数,className所对应的类必须有一个有参的构造方法才行,否则会抛出异常。
3.在运行时获取任意类所具有的属性和方法。
这一节我们讨论如何动态的获取属性和方法,首先我们先讲获取属性吧。
Class类提供我们四个方法获取某类的属性:
Field[] getDeclaredFields() 获取所有此类自己声明的字段,包括任何访问级别。
Field getDeclaredField(String fieldName) 获取指定名字的自己申明的对象。
Field[] getFields() 获取所有(包括父类的)访问级别为public的字段。
Field getField(String fieldName) 获取指定名字访问级别为public的字段,包括父类的。
看完API后,我相信大家应该能够写出来了,我就附上一个例子吧。
public static void showFields(Object o){
Class c=o.getClass();
Field[] fields=c.getDeclaredFields();
for(Field f : fields){
try {
System.out.println("类型:"+f.getGenericType().toString()
+"字段名:"+f.getName()
+"值"+f.get(o));
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的例子有读取字段的值,但如果访问级别不够将会出异常,如要测试,请把相应的字段访问级别改为public.
有关Field类请大家自行查询帮助文档,本文只是起个抛砖引玉的作用,很多东西还得考大家自己去帮助文档中找。
接下来我们学习下动态获取某类的方法。在Class类中也提供了相应的方法,这组方法与获取Field的方法相似,我们来看看:
Method getDeclaredMethod(String name, Class... parameterTypes)
Method[] getDeclaredMethods()
Method getMethod(String name, Class... parameterTypes)
Method[] getMethods()
对这些方法我就不多做介绍了,和获取Field的方法是对应的,请大家参阅JAVA API文档,我给大家一个例子吧:
public static void showMethod(Object o){
Class c=o.getClass();
Method[] methods=c.getDeclaredMethods();
for(Method me : methods){
System.out.println(me.getName());
}
}
它可以打印出指定对象属于类中申明定义的所有方法(不包括父类的)。
4.在运行时调用任意对象的方法。
最实用的来了,动态调用方法。通过它我们可以实现很多很智能的东西,比如Hibernate中的Session,只要调用它的save方法,把一个VO对象放进去它就能帮我们自动生成sql语句,并将其插入到数据库中,酷吧!呵呵,学完这个特性后,我们完全可以实现同样的功能。
我们来看个例子:
public static void invokeMethod(Object o){
Class c=o.getClass();
try {
Method method=c.getMethod("setName", new Class[]{String.class});
method.invoke(o, new Object[]{"yjgoo"});
} catch (Exception e) {
e.printStackTrace();
}
}
这个例子演示了动态的调用方法的方法,首先得到Method对象,这里使用Class对象的getMethod()方法,它有两个参数,第一个是要获取的方法名,第二个是这个方法的参数类型,这里用的是String型,这里应该没问题吧?有问题的话把代码多琢磨下,写下。
找到Method对象后,调用它的invoke()方法,它也需要两个参数,第一个是从中调用这个方法的对象,这里写的是o,因为我们要调用o的setName方法,第二个参数是参数,也是Object的数组,这里setName方法需要的参数是String对象,就传一个String的对象就可以了。
全文就OVER了,不知道大家都看懂了没有,呵呵,希望大家多去看看java API文档,在那里面可以详细的了解反射,通过反射可以做很多事情,本文只介绍了很小一部分。
其中主方法完整的如下: public static void main(String[] args) {
//动态构造UserVo对象
UserVo uv=(UserVo)TestReflection.getInstance("vo.UserVo");
TestReflection.refClassInfo(uv);//动态获取uv对象是哪个类的实例
System.out.println("所有的方法:");
TestReflection.showMethod(uv);//显示uv对象所属类自己定义的所有方法
uv.setName("no name");
TestReflection.showFields(uv);//显示uv对象的所有属性和值
TestReflection.invokeMethod(uv);//动态执行方法,调用setName方法,改变name的值
TestReflection.showFields(uv);//再显示
}
源文件来自:http://hi.baidu.com/cxmjjyizuxbcuvd/item/146688cbda7d7c2c46d5c0d5
Java为我们提供了反射机制,反射——在生物中被这样解释:动物通过中枢神经系统对刺激的一种应答式反应,在物理中它被这样解释:声波、光波或其他电磁波遇到障碍物或别种媒质面而折回,那么它在Java中又该怎么解释呢?首先我们来看看它能做什么:
1. 在运行时判断任意一个实例的所属类。
2. 在运行时构造任意一个类的实例。
3. 在运行时获取任意类所具有的属性和方法。
4. 在运行时调用任意对象的方法。
不知道大家有没有注意到“运行时”这三个字,它能让我们的程序更加动态,更加的灵活,好了,废话少说,我们一个一个来实现上面所说的功能。
在解决以上问题之前,我们先看看java为我们提供了哪些类来实现反射:
Class:它代表一个类,JVM每加载一个类都会实例一个相应的Class对象,如何取得它我们后话再讲。
Field:它代表类的属性。
Method:它代表类的方法。
Constructor:它代表类的构造方法。
1.在运行时判断任意一个实例的所属类。
首先我们准备一个用于测试的Javabean:
package vo;
public class UserVo {
private String name;
public UserVo(){}
public String getName(){
return this.name;
}
public void setName(String name){
this.name=name;
}
}
我们将围绕这个类来进行测试。我们再写一个类名叫:TestReflection,代码如下:
package reflection;
import vo.UserVo;
public class TestReflection {
/**
* 打印类的信息
*/
public void refClassInfo(Object o){
Class c=o.getClass();
System.out.println(c.getName());
}
public static void main(String[] args) {
UserVo t=new UserVo();
new TestReflection().refClassInfo(t);
}
}
现执行下看看效果,是不是动态的获取了类名?接着我们来看看它的实现。
public void refClassInfo(Object o){
Class c=o.getClass();
System.out.println(c.getName());
}
主要就是这个方法了,它有一个Object型的参数,在执行它之前我们并不知道它是属于那个类的,但程序运行时我们就可以通过Class.getName()这个方法来得到。
前面我们说过Class代表一个类,我们在这个例子中,通过调用对象的getClass(),来获取此对象的Class对象,既然它代表类,那么它肯定拥有这个类的所有信息,getName()这个方法就能获得它的类名。
后面的一切操作都是以它为基础的,在java中如果要反射,我们就得现获得Class对象,这个道理很简单,如果你连哪个类都不知道,你怎么去找它的方法?呵呵。
2.在运行时构造任意一个类的实例。
在这个例子中,假设我们知道类名,但没有这个对象,我们通过反射机制来动态的获取一个对象。
public static Object getInstance(String className){
try {
Class c=Class.forName(className);
return c.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
这个例子中,我们接触一种新的获取Class的方法,通过Class.forName(String className)这个方法,得到Class对象后,再调用它的newInstance()即可获得此类的对象。
我们怎么调用这个方法呢?
public static void main(String[] args) {
UserVo t=(UserVo)TestReflection.getInstance("vo.UserVo");
}
上面我们确实获取了实例,但这种方法有个缺点,就是只支持无参的构造函数,如果我们要实例的类它的构造函数是有参的我们该怎么办,这里我们要用到Constructor类,还记得它吗?前面说过它代表构造方法,我们来看代码。
public static Object constructInstance(String className){
try {
Class c=Class.forName(className);
Class[] paramList={String.class};//参数列表
Constructor ctor=c.getConstructor(paramList);
Object[] param={"hello"};
return ctor.newInstance(param);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
首先我先介绍下String.class这个写法,这种方法也可以获取某类的Class对象,这里获取的String的Class对象,至此我们学习三种获取Class的方法。
1. Object.getClass();
2. Class.forName(className);
3. new Object().class;
——接下来我们继续分析代码。
构造好参数列表(形参)后,我们可以通过这个这个参数列表来找一个构造方法:
Constructor ctor=c.getConstructor(paramList);
Class类的getConstructor()方法可以获取指定参数列表的构造方法类:Constructor,Constructor类同样有一个newInstance()的方法,只不过这次得传参数了,这里必须传Object的数组,但我们构造方法的参数是String型的怎么办?根据多态的特性,我们知道父类的引用可以指向子类的对象,这里我们只需在Object数组中放入String的对象就OK了。
Object[] param={"hello"};
最后调用ctor.newInstance(param);获得该对象的实例。
要使用本函数,className所对应的类必须有一个有参的构造方法才行,否则会抛出异常。
3.在运行时获取任意类所具有的属性和方法。
这一节我们讨论如何动态的获取属性和方法,首先我们先讲获取属性吧。
Class类提供我们四个方法获取某类的属性:
Field[] getDeclaredFields() 获取所有此类自己声明的字段,包括任何访问级别。
Field getDeclaredField(String fieldName) 获取指定名字的自己申明的对象。
Field[] getFields() 获取所有(包括父类的)访问级别为public的字段。
Field getField(String fieldName) 获取指定名字访问级别为public的字段,包括父类的。
看完API后,我相信大家应该能够写出来了,我就附上一个例子吧。
public static void showFields(Object o){
Class c=o.getClass();
Field[] fields=c.getDeclaredFields();
for(Field f : fields){
try {
System.out.println("类型:"+f.getGenericType().toString()
+"字段名:"+f.getName()
+"值"+f.get(o));
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的例子有读取字段的值,但如果访问级别不够将会出异常,如要测试,请把相应的字段访问级别改为public.
有关Field类请大家自行查询帮助文档,本文只是起个抛砖引玉的作用,很多东西还得考大家自己去帮助文档中找。
接下来我们学习下动态获取某类的方法。在Class类中也提供了相应的方法,这组方法与获取Field的方法相似,我们来看看:
Method getDeclaredMethod(String name, Class... parameterTypes)
Method[] getDeclaredMethods()
Method getMethod(String name, Class... parameterTypes)
Method[] getMethods()
对这些方法我就不多做介绍了,和获取Field的方法是对应的,请大家参阅JAVA API文档,我给大家一个例子吧:
public static void showMethod(Object o){
Class c=o.getClass();
Method[] methods=c.getDeclaredMethods();
for(Method me : methods){
System.out.println(me.getName());
}
}
它可以打印出指定对象属于类中申明定义的所有方法(不包括父类的)。
4.在运行时调用任意对象的方法。
最实用的来了,动态调用方法。通过它我们可以实现很多很智能的东西,比如Hibernate中的Session,只要调用它的save方法,把一个VO对象放进去它就能帮我们自动生成sql语句,并将其插入到数据库中,酷吧!呵呵,学完这个特性后,我们完全可以实现同样的功能。
我们来看个例子:
public static void invokeMethod(Object o){
Class c=o.getClass();
try {
Method method=c.getMethod("setName", new Class[]{String.class});
method.invoke(o, new Object[]{"yjgoo"});
} catch (Exception e) {
e.printStackTrace();
}
}
这个例子演示了动态的调用方法的方法,首先得到Method对象,这里使用Class对象的getMethod()方法,它有两个参数,第一个是要获取的方法名,第二个是这个方法的参数类型,这里用的是String型,这里应该没问题吧?有问题的话把代码多琢磨下,写下。
找到Method对象后,调用它的invoke()方法,它也需要两个参数,第一个是从中调用这个方法的对象,这里写的是o,因为我们要调用o的setName方法,第二个参数是参数,也是Object的数组,这里setName方法需要的参数是String对象,就传一个String的对象就可以了。
全文就OVER了,不知道大家都看懂了没有,呵呵,希望大家多去看看java API文档,在那里面可以详细的了解反射,通过反射可以做很多事情,本文只介绍了很小一部分。
其中主方法完整的如下: public static void main(String[] args) {
//动态构造UserVo对象
UserVo uv=(UserVo)TestReflection.getInstance("vo.UserVo");
TestReflection.refClassInfo(uv);//动态获取uv对象是哪个类的实例
System.out.println("所有的方法:");
TestReflection.showMethod(uv);//显示uv对象所属类自己定义的所有方法
uv.setName("no name");
TestReflection.showFields(uv);//显示uv对象的所有属性和值
TestReflection.invokeMethod(uv);//动态执行方法,调用setName方法,改变name的值
TestReflection.showFields(uv);//再显示
}
源文件来自:http://hi.baidu.com/cxmjjyizuxbcuvd/item/146688cbda7d7c2c46d5c0d5
发表评论
-
java验证字符串中是否包含数字,对数字的操作
2016-03-15 11:01 9488在javascript中有一个方法 ... -
jdk7 Collections.sort()方法报非法参数异常
2016-03-03 18:57 12064JDK7的Comparison method violates ... -
log4j.properties配置详解
2016-01-18 16:50 1281Log4J的配置文件(Configuration File)就 ... -
Java 日期时间 Date类型,long类型,String类型表现形式的转换
2015-12-24 17:35 3276Java 日期时间 Date类型,long类型,String类 ... -
Java多线程-工具篇-BlockingQueue
2015-11-24 16:13 984Java多线程-工具篇-Block ... -
Java 实例 - 队列(Queue)入门用法
2015-11-23 17:27 2003队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表 ... -
Java中序列化的serialVersionUID作用
2015-11-13 14:13 4819Java序列化是将一个对象 ... -
java的序列化和反序列化
2015-10-27 19:48 1118Java基础学习总结——Jav ... -
java中volatile关键字的含义
2015-08-12 20:10 754java中volatile关键字的含 ... -
Java读写文件中文乱码问题
2015-07-20 17:49 2965问题:在用Java程序进行读写含中文的txt文件时,经常会出现 ... -
String类中split方法的使用
2015-07-02 14:39 984String类中split方法的使用 split 方法:将一个 ... -
PreparedStatement防止SQL注入
2015-04-11 16:27 2792一条效率差的sql语句,足以毁掉整个应用. Stateme ... -
Session的生命周期
2015-04-11 11:58 914我们已经知道,Session是在用户第一次访问网 ... -
JAVA多线程和并发基础
2015-04-11 11:58 770JAVA多线程和并发基础 ... -
Java中equals()与hashCode()方法详解
2015-04-08 16:19 877一.equals()方法详解 equals()方法在o ... -
json数据后台处理
2015-03-30 16:05 793JAVA解析JSON问题,怎么解析,急!! String j ... -
java判断list为空
2015-01-30 15:25 3951java判断list为空 if(null == list | ... -
httpclient使用实践
2015-01-09 17:09 1343httpclient是什么这里不再详述(可参考最下方网址);直 ... -
java反射获取属性和方法
2015-01-09 11:12 3106反射的应用一般是要用到某些特殊类的属性和方法,无论是一般方法还 ... -
java中int 转String位数不够前面补零
2015-01-08 21:53 19937java 中int 转String位数不够前面补零 Stri ...
相关推荐
java反射入门 实现java反射的两种模式
NULL 博文链接:https://navylee.iteye.com/blog/729090
代码为JAVA反射的一个DEMO,适合初学者临摹学习,还附有properties的创建方法,比较基础。
对初学者而言这是一个不错的对jdbc学习的资源。
Java SE编程入门教程 java反射机制(共16页).pptx Java SE编程入门教程 java泛型(共11页).pptx Java SE编程入门教程 java封装继承多态(共56页).pptx Java SE编程入门教程 java集合(共38页).pptx Java SE编程...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
java反射 详解 入门到掌握 自己认为是很好的东东
Java基础入门(四)-泛型、反射、注解
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
对于Java基础的巅峰——反射机制的详细描述,反射的入门学习帮手!
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...
完整版 Java基础入门教程 Java程序语言设计 07 网络编程 反射机制(共23页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络编程 网络编程(共32页).ppt 完整版 Java基础入门教程 Java程序语言设计 07 网络...