今天在和瑾华讨论ASM的时候,通过将反射的method转换为asm的method时遇到反射时数组的问题。当时两个人都卡住了,现在实验通了,顺手记录下来。

原始类:

 
  
  1. public class Person implements China { 
  2.     protected String name; 
  3.  
  4.     public Person(String name) { 
  5.         this.name = name; 
  6.     } 
  7.     public Person(String name1[],String name2) { 
  8.     } 
  9.  
  10.     public String sayHello(String name) { 
  11.         return "welcome " + name; 
  12.     } 
  13.  
  14.     protected void protect() { 
  15.         privatedMethod(); 
  16.     } 
  17.  
  18.     private void privatedMethod() { 
  19.  
  20.     } 
  21.  

通过反射取得构造函数, 通常的方法为:

 
  
  1. @Test 
  2.     public void test04() { 
  3.         try { 
  4.             Class<?> clazz = (Class<?>) Class 
  5.                     .forName("com.alibaba.demoeo.reflect.classes.Person"); 
  6.             Constructor<?>[] constructs = clazz.getConstructors(); 
  7.             for (Constructor<?> construct : constructs) { 
  8.                 System.out.println(construct.getName()); 
  9.             } 
  10.         } catch (Exception e) { 
  11.             e.printStackTrace(); 
  12.         } 
  13.     } 

如果要取得特定参数的构造函数,则为:

 
  
  1. @Test 
  2.     public void test07() { 
  3.         try { 
  4.             Class<?> clazz = (Class<?>) Class 
  5.             .forName("com.alibaba.demoeo.reflect.classes.Person"); 
  6.             Constructor<?> construct = clazz.getConstructor(String.class); 
  7.             System.out.println(construct); 
  8.         } catch (Exception e) { 
  9.             e.printStackTrace(); 
  10.         } 
  11.     } 

问题引出:而要取得含有数组的参数的构造函数如何办呢? 这也是我们卡住的原因,实验了clazz.getConstructor(String.class, String.class); clazz.getConstructor(Array.class, String.class);等都不行, 后来通过反射机制将参数类型输出进行查看,发现数组为:class [Ljava.lang.String;

 
  
  1. @Test 
  2. public void test05() { 
  3.     try { 
  4.         Class<?> clazz = (Class<?>) Class 
  5.         .forName("com.alibaba.demoeo.reflect.classes.Person"); 
  6.         Constructor<?>[] constructs = clazz.getConstructors(); 
  7.          
  8.         for (Constructor<?> construct : constructs) { 
  9.             Class<?>[] types = construct.getParameterTypes(); 
  10.             for(Class<?> type : types){ 
  11.                 System.out.println(type); 
  12.             } 
  13.             System.out.println("-------------"); 
  14.         } 
  15.     } catch (Exception e) { 
  16.         e.printStackTrace(); 
  17.     } 

输出为:

 
  
  1. class java.lang.String 
  2. ------------- 
  3. class [Ljava.lang.String; 
  4. class java.lang.String 
  5. ------------- 

好的,现在知道是什么内容了,那就使用这种类型来构造:

 
  
  1. @Test 
  2.     public void test06() { 
  3.         try { 
  4.             Class<?> clazz = (Class<?>) Class 
  5.             .forName("com.alibaba.demoeo.reflect.classes.Person"); 
  6.             Constructor<?> construct = clazz.getConstructor(Class.forName(("[Ljava.lang.String;")), String.class); 
  7.             System.out.println(construct); 
  8.         } catch (Exception e) { 
  9.             e.printStackTrace(); 
  10.         } 
  11.     } 

测试结果正确,输出如下:

 
  
  1. public com.alibaba.demoeo.reflect.classes.Person(java.lang.String[],java.lang.String) 

考虑getConstructor的参数为可变数组,于是考虑通过传递数组类型给getConstructor方法,经测试后通过,具体如下:

 
  
  1. @Test 
  2.     public void test08() { 
  3.         try { 
  4.             Class<?> clazz = (Class<?>) Class 
  5.             .forName("com.alibaba.demoeo.reflect.classes.Person"); 
  6.             Constructor<?> construct = clazz.getConstructor(new Class[]{String[].class,String.class}); 
  7.             System.out.println(construct); 
  8.         } catch (Exception e) { 
  9.             e.printStackTrace(); 
  10.         } 
  11.     } 

 

使用此方法测试ASM转换:

 
  
  1. public class Demo { 
  2.     public void test(String[] str){} 
  3.     /** 
  4.      * @param args 
  5.      */ 
  6.     public static void main(String[] args) throws Exception{ 
  7.         java.lang.reflect.Method method = Demo.class.getMethod("test", Class.forName("[Ljava.lang.String;")); 
  8.         //java.lang.reflect.Method method = Demo.class.getMethod("test", new Class[]{String[].class}); 
  9.          
  10.         com.alibaba.citrus.asm.commons.Method asmMethod = com.alibaba.citrus.asm.commons.Method.getMethod(method); 
  11.         System.out.println(asmMethod.getDescriptor()); 
  12.     } 

或者

 
  
  1. public class Demo { 
  2.     public void test(String[] str){} 
  3.     /** 
  4.      * @param args 
  5.      */ 
  6.     public static void main(String[] args) throws Exception{ 
  7.         //java.lang.reflect.Method method = Demo.class.getMethod("test", Class.forName("[Ljava.lang.String;")); 
  8.         java.lang.reflect.Method method = Demo.class.getMethod("test"new Class[]{String[].class}); 
  9.          
  10.         com.alibaba.citrus.asm.commons.Method asmMethod = com.alibaba.citrus.asm.commons.Method.getMethod(method); 
  11.         System.out.println(asmMethod.getDescriptor()); 
  12.     } 

测试结果:

 
  
  1. ([Ljava/lang/String;)V 

【注意】

1、今天讨论之后,也可以使用String[].class表达字符串数组也是可以的