A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

【南京校区】反射的妙用


    反射作为一个高薪技术,在框架的底层大量的使用,反射会根据一个字节码文件直接创建出该类的对象。

    即:你给我传递一个类名或者你给我传递一个字节码文件对象,我就可以创建出这个类的对象了。

   所以反射是我们高薪比不可少学习的东西。



(一)
反射或者字节码文件对象的三种方式

   
字节码文件获取的三种方式


1.        对象名.getCalss();                
2.        类名.class                       
3.        Class.forName("全类名");       




代码示例:
        1.通过对象获取
               
[AppleScript] 纯文本查看 复制代码
Student s = new Student();
		s.getClass()
		//getClass() 方法是在哪个类中的?Object
		//为咩这个方法要定义在Object类里面?
		//因为所有的类都有字节码文件,我们要写在所有的类共同的父类中.(向上抽取)
		//因为Object是所有的类直接父类或者间接父类,写在Object中,所有的类都可以用这个方法了
               


       
        2,通过类名.class调用
                Student.class


        3,Class 类中的一个静态方法获取
                Class.forName("全类名");//全类名:包名 + 类名






以上这三种方法,你觉得那种较为灵活,为咩?
        因为第一种和第二种,如果我们想要获取另外类的class对象.
        此时得去修改代码.


        因为第三种,我们可以把全类名写在本地的文本文件中
        然后用IO流,读这一整行. BufferedReader 因为有一个 readLine()
        这个方法的返回值line就是读到的全类名
        这样我们可以和第三种方式这样去结合
        Class.forName(line);




       
[AppleScript] 纯文本查看 复制代码
BufferedReader br = new BufferedReader(new File.......)
	Stbr.ring line = eadLine();
	Class.forName(line);
        此时我们一开始想要获取的是Student.然后第二次我们想要获取Person.
        1.不用到代码中修改代码了
        2,我们只需要修改文本文件中的那段话就可以了


(二)利用反射修改public属性值
Class clazz = Class.forName("com.heima.bean.Person");
先去获取这个类的字节码文件的对象
Constructor c = clazz.getConstructor(String.class,int.class);
获取有参构造        Person p = (Person) c.newInstance("张三",23);
通过有参构造创建对象
通过反射的方式得到Person的对象       
Field f = clazz.getField("name");
获取姓名字段的对象
f.set(p, "李四");
将上面创建的对象中的name赋值成"李四"


(三)利用反射修改非public属性值(暴力反射)
[AppleScript] 纯文本查看 复制代码
	Class clazz = Class.forName("com.heima.bean.Person");			//先去获取这个类的字节码文件的对象
	Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
	Person p = (Person) c.newInstance("张三",23);					//通过有参构造创建对象
	//通过反射的方式得到Person的对象
	Field f = clazz.getDeclaredField("name");						//暴力反射获取字段
	f.setAccessible(true);											//去除私有权限
	f.set(p, "李四");	



(四)利用反射运行一个public修饰的方法
[AppleScript] 纯文本查看 复制代码
利用反射运行一个空参无返回值方法。

	Class clazz = Class.forName("com.heima.bean.Person");

	Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
	Person p = (Person) c.newInstance("张三",23);					//通过有参构造创建对象	
	
	Method m = clazz.getMethod("eat");								//获取eat方法
	m.invoke(p);													//运行这个方法
	//p.eat();//就相当于我们平时写的这样的效果。	


利用反射运行一个有参无返回值方法。
	Class clazz = Class.forName("com.heima.bean.Person");
	
	Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
	Person p = (Person) c.newInstance("张三",23);					//通过有参构造创建对象	
	
	Method m2 = clazz.getMethod("eat", int.class);					//获取有参的eat方法
	m2.invoke(p, 10);												//运行有参的eat方法



利用反射运行一个无参有返回值的方法
	Class clazz = Class.forName("com.heima.demo.Student");
		
	Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
	Student p = (Student) c.newInstance("张三",23);					//通过有参构造创建对象	
	
	Method m2 = clazz.getMethod("getName");							//获取无参的getName方法
	String invoke = (String) m2.invoke(p);							//运行无参的getName。该方法有返回值。
																	//返回值是什么类型就可以强转成什么类型
	System.out.println(invoke);


利用反射运行一个有参有返回值的方法
	Class clazz = Class.forName("com.heima.demo.Student");
		
	Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
	Student p = (Student) c.newInstance("张三",23);					//通过有参构造创建对象	
	
	Method m2 = clazz.getMethod("eat",int.class);					//获取有参的eat方法
	int invoke = (int) m2.invoke(p,20);								//运行有参的eat。该方法有返回值。
																	//返回值是什么类型就可以强转成什么类型
	System.out.println(invoke);			





0 个回复

您需要登录后才可以回帖 登录 | 加入黑马