java反射详解 (二)

 【案例】经过反射操做属性html

  
  
  
  
  1. class hello { 
  2.     public static void main(String[] args) throws Exception { 
  3.         Class<?> demo = null
  4.         Object obj = null
  5.   
  6.         demo = Class.forName("Reflect.Person"); 
  7.         obj = demo.newInstance(); 
  8.   
  9.         Field field = demo.getDeclaredField("sex"); 
  10.         field.setAccessible(true); 
  11.         field.set(obj, "男"); 
  12.         System.out.println(field.get(obj)); 
  13.     } 
  14. }// end class 

 

【案例】经过反射取得并修改数组的信息:java

  
  
  
  
  1. import java.lang.reflect.*; 
  2. class hello{ 
  3.     public static void main(String[] args) { 
  4.         int[] temp={1,2,3,4,5}; 
  5.         Class<?>demo=temp.getClass().getComponentType(); 
  6.         System.out.println("数组类型: "+demo.getName()); 
  7.         System.out.println("数组长度  "+Array.getLength(temp)); 
  8.         System.out.println("数组的第一个元素: "+Array.get(temp, 0)); 
  9.         Array.set(temp, 0100); 
  10.         System.out.println("修改以后数组第一个元素为: "+Array.get(temp, 0)); 
  11.     } 

 

【运行结果】: c++

数组类型: int 数组

数组长度  5 app

数组的第一个元素: 1 ide

修改以后数组第一个元素为: 100工具

【案例】经过反射修改数组大小ui

  
  
  
  
  1. class hello{ 
  2.     public static void main(String[] args) { 
  3.         int[] temp={1,2,3,4,5,6,7,8,9}; 
  4.         int[] newTemp=(int[])arrayInc(temp,15); 
  5.         print(newTemp); 
  6.         System.out.println("====================="); 
  7.         String[] atr={"a","b","c"}; 
  8.         String[] str1=(String[])arrayInc(atr,8); 
  9.         print(str1); 
  10.     } 
  11.       
  12.     /** 
  13.      * 修改数组大小 
  14.      * */ 
  15.     public static Object arrayInc(Object obj,int len){ 
  16.         Class<?>arr=obj.getClass().getComponentType(); 
  17.         Object newArr=Array.newInstance(arr, len); 
  18.         int co=Array.getLength(obj); 
  19.         System.arraycopy(obj, 0, newArr, 0, co); 
  20.         return newArr; 
  21.     } 
  22.     /** 
  23.      * 打印 
  24.      * */ 
  25.     public static void print(Object obj){ 
  26.         Class<?>c=obj.getClass(); 
  27.         if(!c.isArray()){ 
  28.             return
  29.         } 
  30.         System.out.println("数组长度为: "+Array.getLength(obj)); 
  31.         for (int i = 0; i < Array.getLength(obj); i++) { 
  32.             System.out.print(Array.get(obj, i)+" "); 
  33.         } 
  34.     } 

 

 

 

【运行结果】: this

数组长度为: 15 spa

1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================

数组长度为: 8

a b c null null null null null

 

动态代理

【案例】首先来看看如何得到类加载器:

  
  
  
  
  1. class test{ 
  2.       
  3. class hello{ 
  4.     public static void main(String[] args) { 
  5.         test t=new test(); 
  6.         System.out.println("类加载器  "+t.getClass().getClassLoader().getClass().getName()); 
  7.     } 

 

【程序输出】:

类加载器  sun.misc.Launcher$AppClassLoader

其实在java中有三种类类加载器。

1Bootstrap ClassLoader 此加载器采用c++编写,通常开发中不多见。

2Extension ClassLoader 用来进行扩展类的加载,通常对应的是jre\lib\ext目录中的类

3AppClassLoader 加载classpath指定的类,是最经常使用的加载器。同时也是java中默认的加载器。

若是想要完成动态代理,首先须要定义一个InvocationHandler接口的子类,已完成代理的具体操做。

  
  
  
  
  1. package Reflect; 
  2. import java.lang.reflect.*; 
  3.   
  4. //定义项目接口 
  5. interface Subject { 
  6.     public String say(String name, int age); 
  7.   
  8. // 定义真实项目 
  9. class RealSubject implements Subject { 
  10.     @Override 
  11.     public String say(String name, int age) { 
  12.         return name + "  " + age; 
  13.     } 
  14.   
  15. class MyInvocationHandler implements InvocationHandler { 
  16.     private Object obj = null
  17.   
  18.     public Object bind(Object obj) { 
  19.         this.obj = obj; 
  20.         return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj 
  21.                 .getClass().getInterfaces(), this); 
  22.     } 
  23.   
  24.     @Override 
  25.     public Object invoke(Object proxy, Method method, Object[] args) 
  26.             throws Throwable { 
  27.         Object temp = method.invoke(this.obj, args); 
  28.         return temp; 
  29.     } 
  30.   
  31. class hello { 
  32.     public static void main(String[] args) { 
  33.         MyInvocationHandler demo = new MyInvocationHandler(); 
  34.         Subject sub = (Subject) demo.bind(new RealSubject()); 
  35.         String info = sub.say("Rollen"20); 
  36.         System.out.println(info); 
  37.     } 

 

 

【运行结果】:

Rollen  20

类的生命周期

在一个类编译完成以后,下一步就须要开始使用类,若是要使用一个类,确定离不开JVM。在程序执行中JVM经过装载,连接,初始化这3个步骤完成。

类的装载是经过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,而且在堆区建立描述这个类的java.lang.Class对象。用来封装数据。 可是同一个类只会被类装载器装载之前

连接就是把二进制数据组装为能够运行的状态。

 

连接分为校验,准备,解析这3个阶段

校验通常用来确认此二进制文件是否适合当前的JVM(版本),

准备就是为静态成员分配内存空间,。并设置默认值

解析指的是转换常量池中的代码做为直接引用的过程,直到全部的符号引用均可以被运行程序使用(创建完整的对应关系)

完成以后,类型也就完成了初始化,初始化以后类的对象就能够正常使用了,直到一个对象再也不使用以后,将被垃圾回收。释放空间。

当没有任何引用指向Class对象时就会被卸载,结束类的生命周期

将反射用于工厂模式

先来看看,若是不用反射的时候,的工厂模式吧:

 

http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html

 

  
  
  
  
  1. interface fruit{ 
  2.     public abstract void eat(); 
  3.   
  4. class Apple implements fruit{ 
  5.     public void eat(){ 
  6.         System.out.println("Apple"); 
  7.     } 
  8.   
  9. class Orange implements fruit{ 
  10.     public void eat(){ 
  11.         System.out.println("Orange"); 
  12.     } 
  13.   
  14. // 构造工厂类 
  15. // 也就是说之后若是咱们在添加其余的实例的时候只须要修改工厂类就好了 
  16. class Factory{ 
  17.     public static fruit getInstance(String fruitName){ 
  18.         fruit f=null
  19.         if("Apple".equals(fruitName)){ 
  20.             f=new Apple(); 
  21.         } 
  22.         if("Orange".equals(fruitName)){ 
  23.             f=new Orange(); 
  24.         } 
  25.         return f; 
  26.     } 
  27. class hello{ 
  28.     public static void main(String[] a){ 
  29.         fruit f=Factory.getInstance("Orange"); 
  30.         f.eat(); 
  31.     } 
  32.   

 

这样,当咱们在添加一个子类的时候,就须要修改工厂类了。若是咱们添加太多的子类的时候,改的就会不少。

如今咱们看看利用反射机制:

  
  
  
  
  1. package Reflect; 
  2.   
  3. interface fruit{ 
  4.     public abstract void eat(); 
  5.   
  6. class Apple implements fruit{ 
  7.     public void eat(){ 
  8.         System.out.println("Apple"); 
  9.     } 
  10.   
  11. class Orange implements fruit{ 
  12.     public void eat(){ 
  13.         System.out.println("Orange"); 
  14.     } 
  15.   
  16. class Factory{ 
  17.     public static fruit getInstance(String ClassName){ 
  18.         fruit f=null
  19.         try
  20.             f=(fruit)Class.forName(ClassName).newInstance(); 
  21.         }catch (Exception e) { 
  22.             e.printStackTrace(); 
  23.         } 
  24.         return f; 
  25.     } 
  26. class hello{ 
  27.     public static void main(String[] a){ 
  28.         fruit f=Factory.getInstance("Reflect.Apple"); 
  29.         if(f!=null){ 
  30.             f.eat(); 
  31.         } 
  32.     } 

 

 

如今就算咱们添加任意多个子类的时候,工厂类就不须要修改。

 

上面的爱吗虽然能够经过反射取得接口的实例,可是须要传入完整的包和类名。并且用户也没法知道一个接口有多少个可使用的子类,因此咱们经过属性文件的形式配置所须要的子类。

下面咱们来看看: 结合属性文件的工厂模式

首先建立一个fruit.properties的资源文件,

内容为:

  
  
  
  
  1. apple=Reflect.Apple 
  2. orange=Reflect.Orange  

 

而后编写主类代码:

  
  
  
  
  1. package Reflect; 
  2.   
  3. import java.io.*; 
  4. import java.util.*; 
  5.   
  6. interface fruit{ 
  7.     public abstract void eat(); 
  8.   
  9. class Apple implements fruit{ 
  10.     public void eat(){ 
  11.         System.out.println("Apple"); 
  12.     } 
  13.   
  14. class Orange implements fruit{ 
  15.     public void eat(){ 
  16.         System.out.println("Orange"); 
  17.     } 
  18.   
  19. //操做属性文件类 
  20. class init{ 
  21.     public static Properties getPro() throws FileNotFoundException, IOException{ 
  22.         Properties pro=new Properties(); 
  23.         File f=new File("fruit.properties"); 
  24.         if(f.exists()){ 
  25.             pro.load(new FileInputStream(f)); 
  26.         }else
  27.             pro.setProperty("apple""Reflect.Apple"); 
  28.             pro.setProperty("orange""Reflect.Orange"); 
  29.             pro.store(new FileOutputStream(f), "FRUIT CLASS"); 
  30.         } 
  31.         return pro; 
  32.     } 
  33.   
  34. class Factory{ 
  35.     public static fruit getInstance(String ClassName){ 
  36.         fruit f=null
  37.         try
  38.             f=(fruit)Class.forName(ClassName).newInstance(); 
  39.         }catch (Exception e) { 
  40.             e.printStackTrace(); 
  41.         } 
  42.         return f; 
  43.     } 
  44. class hello{ 
  45.     public static void main(String[] a) throws FileNotFoundException, IOException{ 
  46.         Properties pro=init.getPro(); 
  47.         fruit f=Factory.getInstance(pro.getProperty("apple")); 
  48.         if(f!=null){ 
  49.             f.eat(); 
  50.         } 
  51.     } 

下面这个是一个比较完整的反射工具类,用来得到一个类里面属性的具体信息

  
  
  
  
  1. package util; 
  2. import java.lang.reflect.*; 
  3. /** 
  4.  * 获取Class的信息 
  5.  * 
  6.  */ 
  7. public class ClassInfo { 
  8.   //须要反射的JAVA类型 
  9.   private static Class reflectionClass; 
  10.   private static String[][] relation; 
  11.   private static String[] constructors; 
  12.   private static String[] methods; 
  13.   private static String[] fields; 
  14.    
  15.   //加载须要反射的类 
  16.   public static void load(String reflectionClassName) { 
  17.     try { 
  18.       reflectionClass = null
  19.       reflectionClass = Class.forName(reflectionClassName); 
  20.     } catch (ClassNotFoundException e) { 
  21.       System.err.println(e.getMessage()); 
  22.     } 
  23.   } 
  24.   //获取类关系 
  25.   public static String[][] getRelation() { 
  26.     String superClassName = reflectionClass.getSuperclass().getSimpleName(); 
  27.     Class[] interfaceClass = reflectionClass.getInterfaces(); 
  28.     if(superClassName == null
  29.       superClassName = "Have not super class!"
  30.     if (reflectionClass.getInterfaces().length == 0) { 
  31.       relation = new String[2][1]; 
  32.       relation[1][0] = "Have not interface!"
  33.     }else { 
  34.       relation = new String[2][reflectionClass.getInterfaces().length]; 
  35.       for (int i = 0; i < interfaceClass.length; i++) { 
  36.         relation[1][i] = interfaceClass[i].getName(); 
  37.         System.out.println( "interfaceClass:"+relation[1][i] ); 
  38.       } 
  39.     } 
  40.     relation[0][0] = superClassName; 
  41.     System.out.println( "superClassName:"+superClassName ); 
  42.     return relation; 
  43.   } 
  44.   
  45.   //获取构造方法 
  46.   public static String[] getConstructors() { 
  47.     Constructor[] constructor = reflectionClass.getDeclaredConstructors(); 
  48.     constructors = new String[constructor.length]; 
  49.     for (int i = 0; i < constructor.length; i++) { 
  50.       Class[] paramType = constructor[i].getParameterTypes(); 
  51.       String param = ""
  52.       for (int j = 0; j < paramType.length; j++) { 
  53.         param += paramType[j].getSimpleName().toString() + " "
  54.       } 
  55.       constructors[i] = constructor[i].getName().toString()  
  56.                 + "(" + param + ")"
  57.       System.out.println("constructor:"+ constructors[i] ); 
  58.     } 
  59.     return constructors; 
  60.   } 
  61.   //获取类方法 
  62.   public static String[] getMethods() { 
  63.     Method[] method = reflectionClass.getDeclaredMethods(); 
  64.     methods = new String[method.length]; 
  65.     for (int i = 0; i < method.length; i++) { 
  66.       Class[] paramType = method[i].getParameterTypes(); 
  67.       String param = ""
  68.       for (int j = 0; j < paramType.length; j++) { 
  69.         param += paramType[j].getSimpleName().toString() + " "
  70.       } 
  71.       methods[i] = method[i].getName().toString()  
  72.             + "(" + param + ")"
  73.       System.out.println("method:"+ methods[i]); 
  74.     } 
  75.     return methods; 
  76.   } 
  77.   //获取类属性 
  78.   public static String[] getFields() { 
  79.     Field[] field = reflectionClass.getDeclaredFields(); 
  80.     fields = new String[field.length]; 
  81.     for (int i = 0; i < field.length; i++) { 
  82.     field[i].setAccessible( true ); //容许访问私有属性 
  83.       fields[i] = field[i].toGenericString(); 
  84.       String type=field[i].getGenericType().toString(); 
  85.       System.out.println("fields:"+fields[i]+"   type:"+type); 
  86.     } 
  87.     return fields; 
  88.   } 
  89.    
  90.   //私有方法,被外部调用 
  91.   private void testInvoke() { 
  92.     System.out.println("invoke!"); 
  93.   } 
  94.   private void testInvoke(String str) { 
  95.     System.out.println("invoke!:" + str); 
  96.   } 
相关文章
相关标签/搜索