黑马程序员技术交流社区

标题: 反射成员方法如果参数是String[]数组,解决办法 [打印本页]

作者: 刘军亭    时间: 2013-1-22 23:42
标题: 反射成员方法如果参数是String[]数组,解决办法
本帖最后由 刘军亭 于 2013-1-23 17:50 编辑
  1. package cn.liu.javaenhance;
  2. import java.lang.reflect.Method;

  3. /*public class ReflectTest {

  4.         public static void main(String[] args) throws Exception {
  5.                
  6.                 //String类型的一维数组
  7.                 String[] s = {"111","222"};
  8.                
  9.                 Method method = Class.forName("cn.liu.javaenhance.R").getMethod("printArray", String[].class);
  10.                
  11.              //传入的参数必须转换成一个不可拆分的对象,防止jvm进行拆包。或者在数组的外边再给他Object[]{s}打包。
  12.                 method.invoke(null,(Object)s);</font>
  13.         }
  14. }
  15. class R{
  16.         
  17.         public static void printArray (String[] strs){
  18.                 for(String str : strs){
  19.                         System.out.println(str);
  20.                 }
  21.         }
  22. }*/

  23. //-----------------------下面参数是int[]类型---------------------------------------------------------------
  24. public class ReflectTest {

  25.         public static void main(String[] args) throws Exception {
  26.                
  27.                 int[] i = {1,2};
  28.                
  29.                 int[] [] ii = {{1,2},{3,4}};
  30.                 String[] [] ss = {{"111","222"},{"333","444"}};
  31.                
  32.                 Method method = Class.forName("cn.liu.javaenhance.R").getMethod("printArray", int[].class);
  33.                
  34.                //为什么int类型的数组就不用转换成不可拆分的对象了,也不用再给他包一层,防止jvm对参数进行解包了呢?
  35.                 method.invoke(null,i);
  36.                
  37.                 //method.invoke(null,ii);//经过测试int类型二维数组也是没问题的
  38.                 //method.invoke(null,ss);//经过测试String类型二维数组也是没问题的 </font>               
  39.         }        
  40. }
  41. //用来进行反射的类
  42. class R{

  43.         public static void printArray (int[] strs){
  44.                 for(int str : strs){
  45.                         System.out.println(str);
  46.                 }
  47.         }
  48. }
复制代码

作者: cyh8807    时间: 2013-1-22 23:59
本帖最后由 赵彦辉 于 2013-1-23 00:23 编辑

你所要反射的方法是:public static void printArray (int[] strs)
                         或者   public static void printArray(String[] str)
当调用这两个个方法时它们所接受的参数都只有一个,是int数组或者String数组
当程序执行 Method method = Class.forName("cn.liu.javaenhance.R").getMethod("printArray", String[].class);这一行代码时
所传入的参数虽然是String类型的数组,但是JDK1.5为了兼容JDK1.4会将其视作一个Object数组,对其进行拆包,这样传入的参数
就不是一个String[]的参数了,而是好多个参数了,所以必须将其封装成一个Oject对象或者Object[]数组作为参数传递
而对于int[]类型的数组,由于其自身具有自动装箱拆箱功能,其在作为参数传递时,会自动将其包装成一个 Integer[]作为参数传递
因此int类型的数组就不用转换成不可拆分的对象了,也不用再给他包一层,防止jvm对参数进行解包。
而对于二维数组而言,程序在把它作为参数传递时即使进行拆包处理,但是处理后其还是一个数组,因此还是作为一个参数进行传递,
而不是当做很多参数进行处理
不知道这样回答,正确不?我是这样理解的

作者: 刘军亭    时间: 2013-1-23 00:01
自己经过多次的测试总结的一点头绪想法:
对这四个数据分别进行测试:

int[] i = {1,2};
int[] [] ii = {{1,2},{3,4}};
String[] s = {"111","222"};
String[] [] ss = {{"111","222"},{"333","444"}};

发现String[]参数,一维数组必须强转类型,或者再进行Object[]包装处理才行。
int[]{}参数直接传递即可。
二维数组直接传递也可以、
分析原因得出:java1.5为了兼容1.4版本传递多个参数时候可以用Object[]数组进行打包处理。
                java1.5有了可变参数,但是还是要兼容1.4所以1.5保留此种解决方法。当传递的参数是一个String[]类型的数组时候,
                jvm会当成1.4时候的解决方法,接收的参数当成是Object[]数组,对数据进行拆包。但是我们需要的就是String[],不需要拆包。
                所以参数是String[]类型的数组时。解决办法有两个:
                1,在String[]类型的数组外边再包一个Object数组,jvm拆包后正是我们想要的String[]数组。
                2.进行类型强转,告诉jvm我给你的就是一个不可分的参数,不用拆包处理。
但是为什么int类型的一维数组还有二维数组就可以直接传递呢?
                因为 int[]类型的数组虽然也是一个对象,属于Object子类。但是他只是一个Object对象,不是Object[]数组,
                所以jvm把它当成一个不可拆分的对象,并没有把它当成数组。所以不会用1.4时候的多个参数的解决方法,所以它可以直接传递。
               
                二维数组也没有问题,因为1.4时候的解决方法的接收的参数是Object[]数组。二维数组虽然也是Object[]类型,但是在没有强转之前它表面上是一个二维数组,
                不符合1.4时候方法参数的要求,用的是1.5的可变参数。所以没有问题。二维数组为什么没问题本人其实还没有太理解。还靠各位同学多多指点。
作者: 王勇文    时间: 2013-1-23 00:19
  1. package Test1;


  2. import java.lang.reflect.Method;


  3. public class Test7
  4. {
  5. public static void main(String[] args) throws Exception
  6. {

  7. Method m= Test7.class.getMethod("wish", String[].class);
  8. //m.invoke(null, new String[]{"1","2","3"});这种方法是不行的
  9. //因为new String[]{"1","2","3"},程序会看做是wish方法有3个参数,类型都是string的,而不是把这个数组看做是一个参数

  10. m.invoke(null, (Object)new String[]{"1","2","3"});
  11. //1.强制转换
  12. m.invoke(null, new Object[]{new String[]{"1","2","3"}});
  13. //2.用超类的数组形式,new String[]{"1","2","3"}作为参数数组的第一个元素;
  14. //这李说明,我们在写参数的时候,都可以写成数组的形式。
  15. }

  16. public static void wish(String[] strs)
  17. {
  18. for(String str:strs)
  19. {
  20. System.out.println(str);
  21. }
  22. }
  23. }
复制代码
希望这段代码对你有帮助。
作者: 黄锦成    时间: 2013-1-23 10:09
赵彦辉 发表于 2013-1-22 23:59
你所要反射的方法是:public static void printArray (int[] strs)
                         或者   publi ...

“而对于int[]类型的数组,由于其自身具有自动装箱拆箱功能,其在作为参数传递时,会自动将其包装成一个 Integer[]作为参数传递”,这个int[]不会变成Integer[]
作者: 刘军亭    时间: 2013-1-23 17:41
赵彦辉 发表于 2013-1-22 23:59
你所要反射的方法是:public static void printArray (int[] strs)
                         或者   publi ...

二维数组如果拆包的话,那么传过去的就会是好多的一维数组,但是我的方法接收的参数是一个二维的数组,不符合参数的要求。
作者: 刘军亭    时间: 2013-1-23 17:43
黄锦成 发表于 2013-1-23 10:09
“而对于int[]类型的数组,由于其自身具有自动装箱拆箱功能,其在作为参数传递时,会自动将其包装成一个  ...

我也觉得这个类型不会提升。但是还是不太明白其中的原因。我想int[]类型的数组只会当成object对象传递。
作者: 刘军亭    时间: 2013-1-23 17:44
王勇文 发表于 2013-1-23 00:19
希望这段代码对你有帮助。

你没有看清楚我问的问题哦
作者: 黄锦成    时间: 2013-1-23 17:51
刘军亭 发表于 2013-1-23 17:43
我也觉得这个类型不会提升。但是还是不太明白其中的原因。我想int[]类型的数组只会当成object对象传递。 ...

嗯。int[]也是属于Object的




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2