通过反射机制创建一个构造方法中参数数量可变的对象

来源:互联网 发布:录屏大师windows 编辑:程序博客网 时间:2024/05/24 03:38

自学的时候刚看到Class类与Java反射,才开始讲解了Class类得到对应类构造方法的方法。

我们可以用getConstructors()等四个方法得到需要的Constructor构造方法或者其数组,然后再利用Constructor的newInstance方法进行创建对象。

但是我尝试了很多次,都无法直接取到构造方法参数数量可变的Constructor对象,只能直接得到参数数量固定的Constructor,而想要取到前者,则暂时以我自身的知识掌握需要采取其他的方式。

首先创建一个含有需要的构造方法的类A

public class A {//这是一个实验类,含有无参构造方法和三个有参构造方法//其中两个有参构造方法的参数数量可变public A(){System.out.println("无参构造方法");}public A(int i){System.out.println("有参构造方法,参数为一个int");System.out.println("该int值为:"+i);}public A(int...arr){System.out.println("有参构造方法,参数为一个int类型的数组");if (arr.length==0){System.out.println("该数组的容量为0");}else{System.out.print("该数组的值分别为:"+arr[0]);for (int i=1;i<arr.length;i++){System.out.print("-"+arr[i]);}System.out.println();}}public A(String...arr){System.out.println("有参构造方法,参数为一个String类型的数组");if (arr.length==0){System.out.println("该数组的容量为0");}else{System.out.print("该数组的值分别为:"+arr[0]);for (int i=1;i<arr.length;i++){System.out.print("-"+arr[i]);}System.out.println();}}}
对应的我在TestA测试类里写了六个方法用于测试和学习

方法一是测试无参构造方法是否能成功创建对象。

public static void getNull(){System.out.println("---getNull---");Class class1=A.class;try{Constructor<A> constructor=class1.getConstructor(null);A a=constructor.newInstance(null);}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getNull---无参构造方法
方法二和三是测试getConstructor方法的参数必须是数组还是单个,虽然参数形式是一个可变长度数组的形式。[i=1]

public static void getInt1(int i){System.out.println("---getInt1---");Class class1=A.class;try{//错误方式:参数是int,则必须用int.calss;参数是Integer才能用Integer.class//Constructor<A> constructor=class1.getConstructor(Integer.class);Constructor<A> constructor=class1.getConstructor(int.class);A a=constructor.newInstance(i);}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getInt1---有参构造方法,参数为一个int该int值为:1
public static void getInt2(int i){System.out.println("---getInt2---");Class class1=A.class;try{Class[] classs=new Class[]{int.class};Constructor<A> constructor=class1.getConstructor(classs);A a=constructor.newInstance(i);}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getInt2---有参构造方法,参数为一个int该int值为:1
方法四是给getConstructor的参数为一个固定长度的Class数组,由三个int.class组成。

[arr={1,2,3}]

public static void getInts1(int...arr){System.out.println("---getInts1---");Class class1=A.class;try{Class[] classs=new Class[]{int.class,int.class,int.class};Constructor<A> constructor=class1.getConstructor(classs);A a=constructor.newInstance(arr);}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getInts1---错误类型为java.lang.NoSuchMethodException
说明以固定长度的class数组作为参数是得不到我们想要的Constructor对象的。

方法五尝试性地用了一下可能能得到class不确定长度数组的方式,并将其作为参数。[arr={1,2,3}]

public static void getInts2(int...arr){System.out.println("---getInts2---");Class class1=A.class;try{Constructor<A> constructor=class1.getConstructor(int.class.getClasses());A a=constructor.newInstance(arr);/*System.out.println(constructor);A a=constructor.newInstance(null);*/}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getInts2---错误类型为java.lang.IllegalArgumentException输出结果2:(将“A a=constructor.newInstance(arr);”注释并且将原本注释的释放出来)---getInts2---public com.A()无参构造方法
第一个输出结果的错误类型是参数不匹配,也就是说得到的Constructor方法的参数不匹配arr,通过第二个输出结果我们得到结论,这种方式得到的实际上是类的无参构造方法。

方法五是目前我可以想到的能得到一个参数数量可变的构造方法的方式,利用了Constructor类的isVarArgs()方法,该方法判定一个Constructor对象的参数列表是否是可变的,为了测试我又给A类加上了参数为String...arr的构造方法用于区分。

public static void getInts3(int...arr){System.out.println("---getInts3---");Class class1=A.class;try{Constructor<A>[] constructors=class1.getConstructors();for (int i=0;i<constructors.length;i++){System.out.println((i+1)+":"+constructors[i]);System.out.println("该方法的参数数量可变:"+constructors[i].isVarArgs());if (constructors[i].isVarArgs()){try{A a=constructors[i].newInstance(arr);}catch(Exception e2){System.out.println("该方法无法以int[]作为参数创建对象");System.out.println("错误类型为"+e2.getClass().getName());}}}}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getInts3---1:public com.A(java.lang.String[])该方法的参数数量可变:true该方法无法以int[]作为参数创建对象错误类型为java.lang.IllegalArgumentException2:public com.A(int[])该方法的参数数量可变:true有参构造方法,参数为一个int类型的数组该数组的值分别为:1-2-33:public com.A(int)该方法的参数数量可变:false4:public com.A()该方法的参数数量可变:false
成功得到了需要的构造方法,并且用它创建了一个对象。

虽然成功得到了,但是还是觉得应该有某一种方式可以直接得到符合参数要求的单个Constructor对象的方式,而不是在类所有的构造方法中挨个去判定。

= =所以还是有一点纠结,如果在后面的学习中发现了新的方式会补充上来的= =

=================分===============割=================线=======================

找到方法了!!!!找到了妈个鸡!!!!

我们将第四个方法改一下![arr={1,2,3}]

public static void getInts2(int...arr){System.out.println("---getInts2---");Class class1=A.class;try{Constructor<A> constructor=class1.getConstructor((new int[0]).getClass());A a=constructor.newInstance(arr);/*System.out.println(constructor);A a=constructor.newInstance(null);*/}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getInts2---有参构造方法,参数为一个int类型的数组该数组的值分别为:1-2-3
似乎看上去应该是一个数组对象然后调用getClass方法,而不是一个单个的对象调用getClass。

所以我觉得需要继续尝试一下!

现在要对A类的String那个构造方法进行尝试![arr={"str1","str2","str3"}]

public static void getStrs1(String...arr){System.out.println("---getStrs1---");Class class1=A.class;try{Constructor<A> constructor=class1.getConstructor((new String[0]).getClass());System.out.println(constructor);A a=constructor.newInstance(arr);}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getStrs1---public com.A(java.lang.String[])错误类型为java.lang.IllegalArgumentException
很绝望= =参数不匹配,但是明明Constructor对象已经取正确了啊,参数的确是String的可变长度数组啊!

于是我又修改了一下= =

public static void getStrs1(String...arr){System.out.println("---getStrs1---");Class class1=A.class;try{Constructor<A> constructor=class1.getConstructor((new String[0]).getClass());Class[] fields=constructor.getParameterTypes();System.out.println("参数列表长度为:"+fields.length);for (int i=0;i<fields.length;i++){System.out.println((i+1)+"参数类型为:"+fields[i].getName());}System.out.println("参数arr的类型为:"+arr.getClass().getName());System.out.println(constructor);A a=constructor.newInstance(arr);}catch(Exception e){System.out.println("错误类型为"+e.getClass().getName());}}输出结果:---getStrs1---参数列表长度为:11参数类型为:[Ljava.lang.String;参数arr的类型为:[Ljava.lang.String;public com.A(java.lang.String[])错误类型为java.lang.IllegalArgumentException
所以我也不知道说什么好= =明明类型都是[Ljava.lang.String;,但是就是类型不匹配,心好累= =

等知道为什么了再继续写吧= =










0 0