zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    写在博客前面
    JavaAPI学习(一):API && String类 && Stringbuffer && StringBuilder
    Java面向对象(七):Object类 & 内部类 & 单例模式
    Java面向对象(六):抽象方法 & 接口 & 递归
    Java面向对象(五):OOP三大特性之多态 — final 关键字
    Java面向对象(四):OOP三大特性之封装与继承
    Java面向对象(三):Java权限修饰符—static关键字
    Java面向对象(二):成员变量—OOP中的内存管理—构造函数
    Java面向对象(一):方法—初识面向对象
    JavaSE学习(六):随机数—简单的排序算法
  • 原文地址:https://www.cnblogs.com/gnivor/p/4246720.html
Copyright © 2011-2022 走看看