黑马程序员-笔记-反射与内省

来源:互联网 发布:北京粉尘数据 编辑:程序博客网 时间:2024/06/03 10:51

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------

java反射就是讲java的各个组成成员反射成为单独的一个个java类。

[java] view plaincopy
  1. public class ReflectTest {  
  2.   
  3.     /** 
  4.      * class类:java程序中各个java类其实是同一类事物,描述这些事物的类就叫Class 
  5.      *  
  6.      * 反射:将类中的每一个成分解析成为一个相应的类。 
  7.      *  
  8.      * @throws ClassNotFoundException 
  9.      * @throws NoSuchMethodException 
  10.      * @throws SecurityException 
  11.      * @throws InvocationTargetException 
  12.      * @throws IllegalAccessException 
  13.      * @throws InstantiationException 
  14.      * @throws IllegalArgumentException 
  15.      * @throws NoSuchFieldException 
  16.      *  
  17.      *  
  18.      *  
  19.      *  
  20.      *  
  21.      */  
  22.     public static void main(String[] args) throws ClassNotFoundException,  
  23.             SecurityException, NoSuchMethodException, IllegalArgumentException,  
  24.             InstantiationException, IllegalAccessException,  
  25.             InvocationTargetException, NoSuchFieldException {  
  26.   
  27.         // classTest();  
  28.         // constructorTest();  
  29.         // fieldTest();  
  30.         // methodTest();  
  31.         // startBase("itcast.day1.Base");  
  32.         //arrayTest();  
  33.         arrayReflect(new int[]{1,2,3});  
  34.           
  35.           
  36.     }  
  37.   
  38.     //利用数组的反射,这个也就是前面讲的Main方法获取数组元素的方案。  
  39.     //数组的反射是不能获得数组类型的,只能获得各个元素的类型。  
  40.     public static void arrayReflect(Object obj){  
  41.         Class clazz = obj.getClass();  
  42.         if(clazz.isArray()){  
  43.             int length = Array.getLength(obj);  
  44.             for(int i=0;i<length;i++){  
  45.                 System.out.println(Array.get(obj, i));  
  46.             }  
  47.         }else{  
  48.             System.out.println(obj);  
  49.         }  
  50.     }  
  51.       
  52.       
  53.     // 数组与Object的关系  
  54.     public static void arrayTest() {  
  55.   
  56.         int[] i1 = new int[]{1,2,4};  
  57.         int[] i2 = new int[4];  
  58.         int[][] i3 = new int[3][2];  
  59.         String[] i4 = new String[]{"a","b","c","d"};  
  60.         System.out.println(i1.getClass() == i2.getClass());  
  61.         //System.out.println(i1.getClass() == i3.getClass());?  
  62.         //System.out.println(i1.getClass() == i4.getClass());  
  63.         System.out.println(i1.getClass().getName());  
  64.         System.out.println(i1.getClass().getSuperclass().getName());  
  65.           
  66.         System.out.println(i3.getClass().getName());  
  67.         System.out.println(i3.getClass().getSuperclass().getName());  
  68.           
  69.         Object o1 = i1;  
  70.         Object o2 = i3;  
  71.           
  72.         Object[] o3 = i3;  
  73.         Object[] o4 = i4;  
  74.         //Object[] o5 = i1;//基本类型的数组不能转换成为Object的数组。只能当做一个Object  
  75.           
  76.         System.out.println(Arrays.asList(i1));  
  77.         System.out.println(Arrays.asList(i3));  
  78.         System.out.println(Arrays.asList(i4));  
  79.           
  80.     }  
  81.   
  82.     // 使用反射启动某一个java  
  83.     public static void startBase(String javaFile) throws SecurityException,  
  84.             NoSuchMethodException, ClassNotFoundException,  
  85.             IllegalArgumentException, IllegalAccessException,  
  86.             InvocationTargetException {  
  87.         Method main = Class.forName(javaFile).getMethod("main", String[].class);  
  88.         // 不能使用new String[]{"123","abc"}来当做一个String[]进行单一的数据,  
  89.         // 因为为了兼容JDK1.4,jvm会自动对这个String数组拆开,拆成两个String(Object),"123","abc"  
  90.         // main.invoke(null, new String[]{"123","abc"});  
  91.         main.invoke(nullnew Object[] { new String[] { "123""abc" } });// 预装  
  92.         main.invoke(null, (Object) new String[] { "123""abc" });// 强制告诉java,不需要拆箱。  
  93.   
  94.     }  
  95.   
  96.     // 成员方法的反射。  
  97.     public static void methodTest() throws SecurityException,  
  98.             NoSuchMethodException, IllegalArgumentException,  
  99.             IllegalAccessException, InvocationTargetException {  
  100.         Method method1 = String.class.getMethod("charAt"int.class);  
  101.         System.out.println(method1.invoke("abc"1));  
  102.         // java自动装箱功能,new int[]{1,2,4}只是一个Object,new  
  103.         // Object[]{1,2,4}则是传入了3个Objcet  
  104.         // System.out.println(method1.invoke("xyz", new int[]{1} ));  
  105.         System.out.println(method1.invoke("xyz"new Object[] { 1 }));  
  106.         // 静态方法的反射调用。不需要传入对象。  
  107.         // method1.invoke(null, 1);  
  108.     }  
  109.   
  110.     // 成员变量的反射。  
  111.     public static void fieldTest() throws SecurityException,  
  112.             NoSuchFieldException, IllegalArgumentException,  
  113.             IllegalAccessException {  
  114.         ReflectPoint pt1 = new ReflectPoint(15);  
  115.         Field filedy = pt1.getClass().getField("y");  
  116.         // 取出pt1中y成员变量的值。  
  117.         System.out.println(filedy.get(pt1));  
  118.   
  119.         // 通过反射获取私有成员字段。强制取出该字段。但该字段不能使用。  
  120.         Field filedx = pt1.getClass().getDeclaredField("x");  
  121.         // 暴力反射强制使用私有的字段。  
  122.         filedx.setAccessible(true);  
  123.         System.out.println(filedx.get(pt1));  
  124.   
  125.         // 将一个对象中String类型的成员变量的a全部换为b。  
  126.         Field[] fileds = pt1.getClass().getFields();  
  127.         for (Field f : fileds) {  
  128.             // 字节码的比较使用==更专业  
  129.             if (f.getType() == String.class) {  
  130.                 String oldStr = (String) f.get(pt1);  
  131.                 String newStr = oldStr.replace("a""b");  
  132.                 f.set(pt1, newStr);  
  133.             }  
  134.         }  
  135.   
  136.         System.out.println(pt1);  
  137.   
  138.     }  
  139.   
  140.     // 构造方法的反射。Class.newInstace();方法就是调用无参构造方法来实例一个对象,  
  141.     // 这个方法使用了缓存机制,他缓存了无参构造器,源码可以分析反射是一个比较耗时的算法。  
  142.     public static void constructorTest() throws SecurityException,  
  143.             NoSuchMethodException, IllegalArgumentException,  
  144.             InstantiationException, IllegalAccessException,  
  145.             InvocationTargetException {  
  146.         Constructor cons = String.class.getConstructor(StringBuffer.class);  
  147.   
  148.         System.out.println(cons.getDeclaringClass());// 返回该构造器对应的类。  
  149.   
  150.         String obj = (String) cons.newInstance(new StringBuffer("abc"));  
  151.         System.out.println(obj);  
  152.     }  
  153.   
  154.     // 获得Class对象的方法。以及一些关键点。  
  155.     public static void classTest() throws ClassNotFoundException {  
  156.   
  157.         Class c1 = ReflectTest.class;  
  158.         c1 = new ReflectTest().getClass();  
  159.         try {  
  160.             c1 = Class.forName("itcast.day1.ReflectTest");  
  161.         } catch (ClassNotFoundException e) {  
  162.             e.printStackTrace();  
  163.         }  
  164.   
  165.         // 存在九个预定义的Class对象,他们是八个基本类型以及Void。  
  166.         c1 = void.class;  
  167.         System.out.println(c1);  
  168.   
  169.         Class c2 = int.class;  
  170.         Class c3 = Integer.class;  
  171.         Class c4 = Integer.TYPE;// Integer中的一个常量,他是int的字节码。  
  172.         // int 与 Integer的字节码是不同的。  
  173.         System.out.println(c2 == c3);  
  174.         System.out.println(c3 == c4);  
  175.         System.out.println(c2 == c4);  
  176.   
  177.         // 相同的字节码在内存中只会存在一份。  
  178.         Class c5 = String.class;  
  179.         Class c6 = "abc".getClass();  
  180.         Class c7 = Class.forName("java.lang.String");  
  181.         System.out.println(c5 == c6);  
  182.         System.out.println(c6 == c7);  
  183.   
  184.         System.out.println(c4.isPrimitive());  
  185.         // 数组本身是一个对象。  
  186.         System.out.println(int[].class.isPrimitive());// 查看一个字节码是否是基本类型。  
  187.         System.out.println(int[].class.isArray());// 判断一个字节码是否是一个数组。  
  188.   
  189.     }  
  190.   
  191. }  

上面反射中使用到的点类:ReflectPoints,由于反射示例:

[java] view plaincopy
  1. // 用于反射的点。  
  2. public class ReflectPoint {  
  3.     private Date date = new Date();  
  4.     private int x;  
  5.     public int y;  
  6.     public String str1 = "aaabbb";  
  7.     public String str2 = "ababab";  
  8.   
  9.     public ReflectPoint(int x, int y) {  
  10.         super();  
  11.         this.x = x;  
  12.         this.y = y;  
  13.     }  
  14.   
  15.     public String toString() {  
  16.         return str1 + "|||" + str2;  
  17.   
  18.     }  
  19.   
  20.     public Date getDate() {  
  21.         return date;  
  22.     }  
  23.   
  24.     public void setDate(Date date) {  
  25.         this.date = date;  
  26.     }  
  27.   
  28.     public int getX() {  
  29.         return x;  
  30.     }  
  31.   
  32.     public void setX(int x) {  
  33.         this.x = x;  
  34.     }  
  35.   
  36.     public int getY() {  
  37.         return y;  
  38.     }  
  39.   
  40.     public void setY(int y) {  
  41.         this.y = y;  
  42.     }  
  43. }  

利用类加载器来读取配置文件:

[java] view plaincopy
  1. /* 
  2.      * 在实际中,是如何读取那个配置的config.properties文件的。 
  3.      * java中new FileInputStream("config.properties"); 
  4.      * 这个相对目录,是相对与谁?是相对于当前的操作目录。(工程目录。) 
  5.      * 并不是相当于当前类,或者java.exe 
  6.      * 使用绝对路径的话需要路径不能写死,需要传入。 
  7.      * 使用类加载器来解决这个方案。 
  8.      */  
  9.       
  10.     public static void pathTest() throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException{  
  11.           
  12.         //使用类加载器加载文件,就是在classPath配置的根目录位置,开始找文件。  
  13.         //不能以斜杠大头,直接从根目录查找起。  
  14.         InputStream is= ReflectTest2.class.getClassLoader().getResourceAsStream("itcast/day1/config.properties");  
  15.         /*下面写法的,是相对于ReflectTest2.class这个文件的文件位置。 
  16.          * ReflectTest2.class.getResourceAsStream("config.properties");//ReflectTest2.class同目录下的配置文件。 
  17.          * 这个写法又等同于: 
  18.          * ReflectTest2.class.getResourceAsStream("/itcast/day1/config.properties");绝对路径。 
  19.          *  
  20.          */  
  21.           
  22.         Properties prop = new Properties();  
  23.         prop.load(is);  
  24.         is.close();  
  25.         String className = prop.getProperty("className");  
  26.         Test13 base = (Test13)Class.forName(className).newInstance();  
  27.         base.main(null);  
  28.       
  29.     }  

内省与BeanUtils的使用:

[java] view plaincopy
  1. public class IntroSpectorTest {  
  2.   
  3.     /** 
  4.      * 内省:IntroSpector 
  5.      *  
  6.      * JavaBean:特殊的java类,符合一系列规范,set/get方法。 javaBean依然可以当做普通类处理。 
  7.      * javaBean只与set,get有关,其属性名是get/set方法后边的部分 如果第二个字母是小写,则把第一个字母变成小的。 
  8.      * 第二个字母是大的,则依然是大写。 
  9.      *  
  10.      * getAge()-->age getCPU()-->CPU 
  11.      *  
  12.      * @throws IntrospectionException 
  13.      * @throws InvocationTargetException 
  14.      * @throws IllegalAccessException 
  15.      * @throws IllegalArgumentException 
  16.      * @throws NoSuchMethodException  
  17.      *  
  18.      */  
  19.     public static void main(String[] args) throws IntrospectionException,  
  20.             IllegalArgumentException, IllegalAccessException,  
  21.             InvocationTargetException, NoSuchMethodException {  
  22.         ReflectPoint pt1 = new ReflectPoint(35);  
  23.         String propertyName = "x";  
  24.         Object retVal = getProperty(pt1, propertyName);  
  25.         System.out.println(retVal);  
  26.         setProperty(pt1, propertyName, 7);  
  27.         System.out.println(pt1.getX());  
  28.           
  29.         //BeanUtils要求所操作的bean必须是public类。  
  30.         //甚至可以操作并不存在的属性。  
  31.         BeanUtils.setProperty(pt1, "tt""9");//这个位置并没有异常。  
  32.         System.out.println(pt1.getX());  
  33.         BeanUtils.setProperty(pt1, "date.time""9999");//支持级联操作,属性链。  
  34.         System.out.println(BeanUtils.getProperty(pt1, "date.time"));  
  35.         System.out.println(pt1.getDate().getTime());  
  36.           
  37.         //BeanUtils对Map的操作。  
  38.         Map<String,String> map= new HashMap<String,String> ();  
  39.         map.put("i""555");  
  40.         BeanUtils.setProperty(map, "i""444");  
  41.         //System.out.println(map.get("myself"));  
  42.         System.out.println(BeanUtils.getProperty(map, "i"));  
  43.         System.out.println(map.get("i"));  
  44.           
  45.         PropertyUtils.setProperty(pt1, "x"999);//PropertyUtils不会进行类型的转换。后边不能写成字符串形式。  
  46.         System.out.println(pt1.getX());  
  47.     }  
  48.       
  49.     // javaBean的复杂操作。  
  50.     private static Object getProperty(Object obj, String propertyName)  
  51.             throws IntrospectionException, IllegalAccessException,  
  52.             InvocationTargetException {  
  53.         /*PropertyDescriptor pd = new PropertyDescriptor(propertyName, 
  54.                 obj.getClass()); 
  55.         Method methodGetX = pd.getReadMethod(); 
  56.         Object retVal = methodGetX.invoke(obj); 
  57.         */  
  58.         BeanInfo info = Introspector.getBeanInfo(obj.getClass());  
  59.         PropertyDescriptor[] pds = info.getPropertyDescriptors();  
  60.         Object retVal =null;  
  61.         for(PropertyDescriptor pd :pds){  
  62.             if(pd.getName().equals(propertyName)){  
  63.                 retVal = pd.getReadMethod().invoke(obj);  
  64.                 break;  
  65.             }  
  66.         }  
  67.           
  68.           
  69.         return retVal;  
  70.     }  
  71.   
  72.     // 方法的抽取:Refactor->重构。Extract Method  
  73.     private static void setProperty(Object obj, String propertyName,  
  74.             Object value) throws IntrospectionException,  
  75.             IllegalAccessException, InvocationTargetException {  
  76.         PropertyDescriptor pd = new PropertyDescriptor(propertyName,  
  77.                 obj.getClass());  
  78.         Method methodSetX = pd.getWriteMethod();  
  79.         methodSetX.invoke(obj, value);  
  80.     }  
  81.   
  82. }  




原创粉丝点击