Java学习笔记--反射
参考资料:
Rollen Holt的博客: http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html
C'est la vie的博客: http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html
coolszy的博客: http://coolszy.iteye.com/blog/569846
leeon的博客: http://www.cnblogs.com/octobershiner/archive/2012/03/18/2404751.html
感谢上面4位博主
一、什么是反射机制
简单的来说,反射机制指的是程序在运行时能够获取自身的信息。
在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
二、哪里用到反射机制
有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,jdbc用过一行码,Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成 驱动对象实例,并不知道它的具体含义。听了反射机制这节课后,才知道,原来这就是反射,现在很多开框架都用到反射机制,hibernate、struts都是用反射机制实现的。
三、反射机制的优点与缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多 态的应用,有以降低类之间的耦合性。一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。
四、利用反射机制能获得什么信息
类中有什么信息,它就可以获得什么信息,不过前提是得知道类的名字,要不就没有后文了
首先得根据传入的类的全名来创建Class对象。
Class c=Class.forName("className"); 注:className必须为全名,也就是得包含包名,比如,cn.netjava.pojo.UserInfo;
Object obj=c.newInstance(); //创建对象的实例
OK,有了对象就什么都好办了,想要什么信息就有什么信息了。
获取类型信息
在没有对象实例的时候,主要有三种办法。
//获得类类型的三种方式
Class classtype1 = Class.forName("com.evor.test.Person"); Class classtype2 = new Person().getClass(); Class classtype2 = Person.class;
第一种方式中,forName中的参数一定是完整的类名(包名+类名),并且这个方法需要捕获异常。
4.1 获得构造器的方法
首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象
| Constructor getConstructor(Class[] params) | 根据指定参数获得public构造器 |
| Constructor[] getConstructors() | 获得public的所有构造器,类中第一个构造器下标为0 |
| Constructor getDeclaredConstructor(Class[] params) | 根据指定参数获得public和非public的构造器 |
| Constructor[] getDeclaredConstructors() | 获得public的所有构造器 |
从名字来看,还是很好懂的,带上Declared的都是获得所有的构造方法,包括私有。
列举上面几种方法如何使用
1.
//指定参数列表获取特定方法,此处没参数,为默认构造方法 Constructor<?> constr1 =classtype1.getDeclaredConstructor();
Object obj1 = constr1.newInstance(new Object[]{});//使用构造器创建实例
2.
//指定参数列表获取特定方法 Constructor<?> constr2 = classtype2.getDeclaredConstructor(new Class[]{String.class,String.class,String.class,int.class}); //输出构造器名 System.out.println(constr2); //使用构造器创建实例 Object obj2 = constr2.newInstance(new Object[]{"20000001","李明","男",19}); //创建一个实例
3.
//获取所有的构造方法集合 Constructor<?> constr3[] =classtype1.getDeclaredConstructors(); //使用构造器创建实例 Object obj3 = constr3[1].newInstance(new Object[]{"30000001","张三","男",27});
4.2 获得类方法的方法
| Method getMethod(String name, Class[] params) | 根据方法名,参数类型获得方法 |
| Method[] getMethods() | 获得所有的public方法 |
| Method getDeclaredMethod(String name, Class[] params) | 根据方法名和参数类型,获得public和非public的方法 |
| Method[] getDeclaredMethods() | 获得所以的public和非public方法 |
Method method = classtype1.getMethod("getInfo");//获取getInfo()方法
Object infoobj1 = method.invoke(obj1); //使用方法,获取人的信息
System.out.println((String)infoobj1); //输出返回值
4.3 获得类中属性的方法
| Field getField(String name) | 根据变量名得到相应的public变量 |
| Field[] getFields() | 获得类中所以public的方法 |
| Field getDeclaredField(String name) | 根据方法名获得public和非public变量 |
| Field[] getDeclaredFields() | 获得类中所有的public和非public方法 |
Field fields[] = classtype1.getDeclaredFields(); //part1 获取类的所有属性 for(int i = 0 ; i <3 ; i ++){ fields[i].setAccessible(true); System.out.print((String)fields[i].get(obj2)+" "); } Field fieldsno = classtype1.getDeclaredField("age");//part2 获取年龄属性 fieldsno.setAccessible(true);//不设置可能发生异常 int s1_age =(int)fieldsno.get(obj2); System.out.println(s1_age);
输出结果:20000001 李明 男 19
实例:
public class Test1{
public static void main(String args[]){
Class<?> classtype1 = null; //类类型
Class<?> classtype2=null;
Class<?> classtype3=null;
try{
classtype1=Class.forName("com.evor.test.Person"); //获得类类型
}catch(Exception e){
}
classtype2 = new Person().getClass(); //另一种获得类类型的方式
classtype3 = Person.class; //另一种获得类类型的方式
System.out.println("类名称"+classtype1.getName());
System.out.println("类名称"+classtype2.getName());
System.out.println("类名称"+classtype3.getName());
System.out.println("三种类实质上类型是一样的,只是获得类型方式不同");
try {
//获取构造器
Constructor<?> constr1 =classtype1.getDeclaredConstructor();
Constructor<?> constr2 = classtype2.getDeclaredConstructor(new Class[]{String.class,String.class,String.class,int.class});
//输出构造器名
Constructor<?> constr3[] =classtype1.getDeclaredConstructors();
constr3[1].newInstance(new Object[]{"30000001","张三","男",27});
constr1.setAccessible(true);//设置可访问的权限
System.out.println("构造器1:"+constr1);
System.out.println("构造器2:"+constr2);
System.out.println("构造器组:"+constr3);
//使用构造器创建实例
Object obj1 = constr1.newInstance(new Object[]{});
Object obj2 = constr2.newInstance(new Object[]{"20000001","李明","男",19}); //创建一个实例
System.out.println("对象1:"+obj1);
System.out.println("对象2:"+obj2);
//获取类的方法,并使用
System.out.println("========获取方法并使用========");
Method method = classtype1.getMethod("getInfo");//获取getInfo()方法
Object infoobj1 = method.invoke(obj1); //使用方法,获取人的信息
Object infoobj2 = method.invoke(obj2); //使用方法
System.out.println((String)infoobj1); //输出返回值
System.out.println((String)infoobj2);
//获取类的属性,并使用
System.out.println("========获取属性========");
Field fields[] = classtype1.getDeclaredFields();//获取类的所有属性
for(int i = 0 ; i <3 ; i ++){
fields[i].setAccessible(true);
System.out.print((String)fields[i].get(obj2)+" ");
}
Field fieldsno = classtype1.getDeclaredField("age");//获取年龄属性
fieldsno.setAccessible(true);//不设置可能发生异常
int s1_age =(int)fieldsno.get(obj2);
System.out.println(s1_age);
} catch (Exception e) {
e.printStackTrace();
}
/*
System.out.println("================");
Method[] method = classtype1.getMethods(); //获取类的方法
for(int i=0;i<method.length;++i){
Class<?> returnType = method[i].getReturnType(); //获取方法的返回值类型
Class<?> para[] = method[i].getParameterTypes(); //获取方法的参数类型表
int temp = method[i].getModifiers();
System.out.print(Modifier.toString(temp)+" ");
System.out.print(returnType.getName()+ " ");
System.out.print(method[i].getName()+" ");
System.out.print("(");
for(int j = 0 ; j <para.length ; j++){
System.out.print(para[j].getName()+" "+"arg"+j);
if(j<para.length-1){
System.out.print(",");
}
}
Class<?> exce[]=method[i].getExceptionTypes();
if(exce.length>0){
System.out.print(") throws ");
for(int k=0;k<exce.length;++k){
System.out.print(exce[k].getName()+" ");
if(k<exce.length-1){
System.out.print(",");
}
}
}else{
System.out.print(")");
}
System.out.println();
}*/
}
}
class Person{
private String sno ;
private String sname ;
private String sex ;
private int age;
public Person(){
this.sno = "unknow";
this.sname = "unknow";
this.sex = "unknow";
this.age = 0;
}
public Person(String sno, String sname , String sex , int age){
this.sno = sno;
this.sname = sname;
this.sex = sex;
this.age = age;
}
public void setSno(String sno){
this.sno = sno;
}
public void setSname(String sname){
this.sname = sname;
}
public void setSex(String sex){
this.sex = sex;
}
public void setAge(int age){
this.age = age;
}
public String getSno() {
return sno;
}
public String getSname() {
return sname;
}
public String getSex() {
return sex;
}
public int getAge() {
return age;
}
public String getInfo(){
return "学号:"+sno+",姓名:"+sname+",性别:"+sex+",年龄:"+String.valueOf(age);
}
}
输出
类名称com.evor.test.Person
类名称com.evor.test.Person
类名称com.evor.test.Person
三种类实质上类型是一样的,只是获得类型方式不同
构造器1:public com.evor.test.Person()
构造器2:public com.evor.test.Person(java.lang.String,java.lang.String,java.lang.String,int)
构造器组:[Ljava.lang.reflect.Constructor;@1db9742
对象1:com.evor.test.Person@106d69c
对象2:com.evor.test.Person@52e922
========获取方法并使用========
学号:unknow,姓名:unknow,性别:unknow,年龄:0
学号:20000001,姓名:李明,性别:男,年龄:19
========获取属性========
20000001 李明 男 19

浙公网安备 33010602011771号