• java反射


    本文按照以下思路帮助自己和路人理清反射。

    1.什么是反射?

    2.反射能干什么?

    3.怎么用?

    4.案例实操:

    5.总结:

    一、什么是反射?

        百度百科:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及

      动态调用对象方法的功能称为java语言的反射机制。

      说的通俗一点,反射是在程序编译完成后,在.class运行阶段起作用的,你给我传过来什么,我都能访问它祖宗十八代,从而达到我的目的。重点在于动态,动态指的是运行阶段,而非编译阶段。

    二、反射能干什么?

      常见的有加载数据库驱动中Class.forName(driverClass),还有许多框架例如spring也大量的使用反射,还有自己的项目中抽取dao层公共方法写到BaseDaoImpl中需要知道传递的实体类型等等,都可以通过反射来获取。

    三、怎么用?

      三种方式可以选择,总之是要获取Class类对象

      3.1.通过对象(不常用,对象都有了还反过用对象再反射属性方法,多此一举)

        Person p = new Person();

        Class<? extends Person> clazz = p.getClass();

      3.2.通过类名(不常用,没有必要)

        Class<? extends Person> clazz = Person.class();

      3.3.通过字符串全类名(常用,一般情况下,我们没法传递过去一个类对象,但是我们可以通过该类的全限定名,间接得到类的信息)

        Class<?> clazz = Class.forName("com.xx.myReflect");

    四、案例实操

      前面都很简单,下面就使用第三种方式,具体测试反射在字段,普通方法,构造方法上的一些使用,其余的类似,自己探索,被测试的类如下。

      4.1 测试字段

      

    @Test
    	public void testField(){
    		try {
    			//通过反射在运行期间加载MyReflect类的.class文件,得到Class对象,Class对象的详细描述了呗代理类
    			Class<?> clazz =  Class.forName("com.cissst.vo.MyReflect");
    			//因为要给字段中设值,因此产生Reflect的实例,父类是Object
    			Object object = clazz.newInstance();
    			//得到本类(不包含父类)中的声明字段数组
    			Field[] fields = clazz.getDeclaredFields();
    			//循环设置字段值,输出字段值
    			for(Field f : fields){
    				//因为某些字段或者方法是私有的,反射需要将此标识设置为true
    				f.setAccessible(true);
    				//判断如果当前字段类型是否是Integer
    				//如果使用getName,获取的是全限定名
    				if(f.getType().getSimpleName().equals("Integer")){
    					//是设置为1
    					f.set(object, 1);
    				}
    				//判断如果当前字段类型是否是String
    				if(f.getType().getSimpleName().equals("String")){
    					//是设置为..
    					f.set(object, "秦琼");
    				}
    				//最后输出,腰肢具体详情请查看API
    				System.out.println(f.get(object));
    			}
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (InstantiationException e) {
    			e.printStackTrace();
    		} catch (IllegalAccessException e) {
    			e.printStackTrace();
    		}
    	}
    

      4.2 测试方法

    /*
    	 * 测试普通方法
    	 */
    	@Test
    	public void testMethod(){
    			try {
    				//通过反射在运行期间加载MyReflect类的.class文件,得到Class对象,Class对象的详细描述了呗代理类
    				Class<?> clazz = Class.forName("com.cissst.vo.MyReflect");
    				//产生Reflect的实例,父类是Object
    				Object object = clazz.newInstance();
    				//指定方法名,指定参数类型,得到该方法,还有方法查API,很好用
    				Method method = clazz.getMethod("method", String.class);
    				//执行此方法
    				method.invoke(object, "李逵");
    			} catch (Exception e) {
    				e.printStackTrace();
    			} 
    	}
    

      4.3 测试构造方法

      

    /*
    	 * 测试构造方法
    	 * 
    	 */
    	@Test
    	public void testConstractorMethod(){
    		try {
    			//通过反射在运行期间加载MyReflect类的.class文件,得到Class对象,Class对象的详细描述了呗代理类
    			Class<?> clazz = Class.forName("com.cissst.vo.MyReflect");
    			//调用无参构造
    			Constructor<?> constructor = clazz.getDeclaredConstructor();
    			//通过无参构造实例化得到类对象
    			Object obj1 = constructor.newInstance();
    			//看得到的ojb和MyReflect是否是同一宗亲
    			System.out.println(obj1 instanceof MyReflect);
    			//得到所有的构造
    			Constructor<?>[] constructors = clazz.getDeclaredConstructors();
    			//循环操作构造
    			for(Constructor<?> con : constructors){
    				//这里做个简单的判断,实际可能比这更复杂
    				if(con.getParameterCount()==0){
    					//无参构造实例化
    					Object ojb2 = con.newInstance();
    					//有参构造
    				}else if(con.getParameterCount()==2){
    					//有参构造实例化
    					Object ojb3 = con.newInstance(1,"林彪");
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} 
    	}
    

    被测试类:

    package com.cissst.vo;
    
    /**
     * 普通类:用此类测试反射
     * @author phoebe
     */
    public class MyReflect{
    	
    	//字段
    	private Integer id;
    	private String name;
    	
    	
    	/*
    	 * 无参构造方法
    	 */
    	public MyReflect(){
    		System.out.println("无参构造is running");
    	}
    	
    	/*
    	 * 有参构造方法
    	 */
    	public MyReflect(Integer id,String name){
    		this.id = id;
    		this.name = name;
    		System.out.println("有参构造");
    	}
    	
    	/*
    	 * 无参普通方法
    	 */
    	public void method(){
    		System.out.println("无参普通方法");
    	}
    	/*
    	 * 无参普通方法
    	 */
    	public void method(String str){
    		System.out.println("有参普通方法");
    	}
    	
    }
    

    五、总结

      反射使得代码更灵活,可以提高复用性。

    Best Regards
  • 相关阅读:
    【青橙商城-管理后台开发】2. 商品服务模块搭建
    【青橙商城-管理后台开发】1.公共模块搭建
    Oracle对象-视图和索引
    Oracle的查询-分页查询
    Oracle的查询-子查询
    Oracle的查询-自连接概念和联系
    Oracle的查询-多表查询中的一些概念
    Oracle的查询-分组查询
    Oracle的查询-多行查询
    dotnet 开源库
  • 原文地址:https://www.cnblogs.com/pecool/p/8414222.html
Copyright © 2020-2023  润新知