黑马程序员——java基础——反射

来源:互联网 发布:安卓翻墙哪个软件好 编辑:程序博客网 时间:2024/06/09 20:53

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

学习反射首先要明白三个问题,明白了这三个问题,反射你就懂了。

第一个问题是什么是反射?

java类中有很多成分,例如:成员变量,方法,构造函数,包,将这些成员年变量也用一个一个相应的类来表示,因此反射就是将java中的成员变量映射成相应的java类。

那么问题来了,映射成那些类了呢?怎么获取这些类呢?

映射成了例如:Method,Field,Contructor,package等等一些类,获取这些类就要讲到反射基石Class,这个Class与class是不同的,他们的区别是:

classJava中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。

Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。例如人对应的是Person类,Java类对应的就是ClassClassJava程序中各个Java类的总称;它是反射的基石,通过Class类来使用反射。

那么我们要得到Method这个类的对象,就要使用到类的字节码,Method是成员变量,它属于哪个类,我们要确定,怎么确定?通过该类的字节码,怎么得到该类的字节码?通过三种方式:

1:类名.class。

2:Class.forname("类的全名称")。这个方法在做框架的时候用到的最多,因为他是有参数的,我们可以事先不知道它是哪个类的字节码,通过传入参数我们才可以根据字符串得知它是哪个类的字节码,通过字节码对象我们就可以,得到该类的一些成分。

3:通过类的对象,对象.getclass()。

三种方法的到同一个类的字节码是相同的代码演示:

<span style="font-size:18px;">package com.itheima.dayo4;public class ReflectionDeom {public static void main(String[] args) {String str="qwe";Class cla=String.class;try {Class cla1=Class.forName("java.lang.String");Class cla2=str.getClass();System.out.println(cla==cla1);System.out.println(cla1==cla2);} catch (ClassNotFoundException e) {e.printStackTrace();}}</span>
有结果可知,无论哪种方式的到的字节码都是一样的,所以一个类,在内存中只存在一份字节码。

如何获取Method,Field,Contructor,package这些类的对象,代码演示:

<span style="font-size:18px;">import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;class Reflection{private int x;private String y;public Reflection(int x, String y) {super();this.x = x;this.y = y;}}public class ReflectionDeom1 {public static void main(String[] args) {String str="wer";try {Constructor constructor=String.class.getConstructor(StringBuffer.class);//通过类的字节码得到构造类中构造函数类的对象try {String str1=(String) constructor.newInstance(new StringBuffer("wor"));//确定调用那个构造函数System.out.println(str.charAt(1)+""+str1.charAt(1));} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();}Reflection ref=new Reflection(4,"wet");         try {Field field=ref.getClass().getDeclaredField("y");field.setAccessible(true);try {String str1=(String) field.get(ref);System.out.println(str1);} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchFieldException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}</span>

上述代码得到了一个类的字节码class,然后通过字节码得到Constructor,Field最后再得到Object,也就是各种类型。

第二个问题是为什么会有反射?

反射有什么用?为什么要反射?刚学习的时候肯定有这写疑问,那好我就用一个反射示例来解释这个为什么要反射代码示例:

<span style="font-size:18px;"></span><pre name="code" class="java"><pre name="code" class="java"><span style="font-size:18px;">package com.itheima.dayo4;import java.lang.reflect.Field;public class ReflectionDeom2 {public String s1="baskedeball";public String s2="goodmoeingallb";public String s3="reflectiobbbn";@Overridepublic String toString() {return "ReflectionDeom2 [s1=" + s1 + ", s2=" + s2 + ", s3=" + s3 + "]";}public static void main(String[] args) {ReflectionDeom2 ref=new ReflectionDeom2();change(ref);System.out.println(ref);}private static void change(Object obj) {Field[] fields=obj.getClass().getFields();//得到类中所有的成员变量for(Field field:fields)//遍历这些成员变量的字段{if(field.getType()==String.class){//比较这些字段类型是不是字符串字节码try {String oldvalue=(String) field.get(obj);//得到这个对象的字符串成员变量String newvalue=oldvalue.replace('b', 'a');//调用字符串中的的方法改变字符串中的字符field.set(obj, newvalue);//将改变了字符的字符串设置成当前对象的的字符串System.out.println(obj);} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}// TODO Auto-generated method stub}}</span>



上面代码很好的解释了反射有什么用,跟为什么要反射,就是我们在写程序的时候,我不知到我这个方法要用到哪个类,来一个类我就接受一个类,然后使用类中的成分。你给我一个对象我就可以通过反射把你类中的成员换掉,这个程序很好的解释了字段的反射,很好的运用它,我们就可以很好的知道所有类中的成员变量。


反射是怎么用的?

反射该怎么用,怎么样才算用到了反射,现在举个例子。我们平时调用类的方法是先创建这个类的对象,通过对象来调用这个类中的方法,比如我们要调用String类中的replace(),首先我们先要创建一个String的对象 String str=“”;然后再通过str.replace()调用该方法,如果我们学会了反射,我们就可以利用反射来调用类中的方法,反射是怎么调用的呢?代码如下:

<span style="font-size:18px;">public class ReflectionMethodDeom {public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {String s="asdfghjkl";char c=s.charAt(2);//原始方法调用类中的方法try {Method method=String.class.getMethod("charAt", int.class);//得到类中分具体方法char c2=(char) method.invoke(s, 2);//设置这个方法对应哪个对象System.out.println(c+""+c2);} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}</span>
通过这个代码,我们就更加清楚了,传统方法是通过对象来调用方法,反射是通过方法来设置对象,这就是方法的反射,这里注意的一点是,如果invoke(null,new Object(1))这个方法中的第一个变量为null,这说明我们调用的这个方法是静态方法,没有对象。

反射总结:

我们用反射来干什么,其实主要是做框架,例如前面提到的,我们在写程序的时候我们要调用一个类的的方法,但是我们不知到我们要调用哪个类的方法,这个是后就要用到反射,就好比框架,框架先出来,我们用框架的程序还在构思。最后说一下,框架和工具类的差别:

框架是别人做好了调用我们写的程序,工具类是我们写的程序需要调用工具类,这是完全相反的,所以说反射带来的便捷减少了项目成本,和开发时间。





0 0
原创粉丝点击