A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张yy 中级黑马   /  2013-7-19 13:13  /  1083 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张yy 于 2013-7-20 15:37 编辑

通过反射  访问构造方法
代码如下:
  1. class Example_01 {

  2.         String s;
  3.         int i,i2,i3;
  4.         private Example_01(){
  5.                
  6.         }
  7.         
  8.         protected Example_01(String s,int i){
  9.                 this.s = s;
  10.                 this.i = i;
  11.         }
  12.         
  13.         public Example_01(String...strings)throws NumberFormatException{
  14.                
  15.                 if(strings.length>0)
  16.                         i = Integer.valueOf(strings[0]);
  17.                 if(strings.length>1)
  18.                         i2 = Integer.valueOf(strings[1]);
  19.                 if(strings.length>2)
  20.                         i3 = Integer.valueOf(strings[2]);
  21.                
  22.         }
  23.         
  24.         public void print(){
  25.                 System.out.println("s="+s);
  26.                 System.out.println("i="+i);
  27.                 System.out.println("i2="+i2);
  28.                 System.out.println("i3="+i3);
  29.         }

  30. }
复制代码

  1. import java.lang.reflect.*;

  2. public class Reflect_Constructor {

  3.         /**
  4.          * @param args
  5.          */
  6.         public static void main(String[] args) {
  7.                 Example_01 example = new Example_01();
  8.                 Class exampleC = example.getClass();
  9.                
  10.                 //获取所有构造方法
  11.                 Constructor[] declaredConstructors = exampleC.getDeclaredConstructors();
  12.                
  13.                 for(int i=0;i<declaredConstructors.length;i++){
  14.                         //遍历构造方法
  15.                         Constructor constructor = declaredConstructors[i];
  16.                         System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());
  17.                         
  18.                         System.out.println("该构造方法的入口参数类型依次为:");
  19.                         //获取所有参数类型
  20.                         Class[] parameterTypes = constructor.getParameterTypes();
  21.                         for(int j=0;j<parameterTypes.length;j++){
  22.                                 System.out.println(""+parameterTypes[j]);
  23.                         }
  24.                         
  25.                         System.out.println("该构造方法可能抛出的异常类型为:");
  26.                         //获取所有可能抛出的异常信息类型
  27.                         Class[] exceptionTypes = constructor.getExceptionTypes();
  28.                         for(int j=0;j<exceptionTypes.length;j++){
  29.                                 System.out.println(""+exceptionTypes[j]);
  30.                         }
  31.                         
  32.                         
  33.                         Example_01 example2 = null;
  34.                         while(example2 == null){
  35.                                 //如果该成员变量的访问权限为private,则抛出异常,即无法访问
  36.                                 try{
  37.                                         //通过执行默认没有参数的构造方法创建对象
  38.                                         if(i == 2)
  39.                                                 example2 = (Example_01) constructor.newInstance();
  40.                                        
  41.                                         //通过执行具有两个参数的构造方法创建对象
  42.                                         else if(i == 1)
  43.                                                 example2 = (Example_01) constructor.newInstance("7",5);
  44.                                        
  45.                                         //通过执行具有可变数量参数的构造方法创建对象
  46.                                         else{
  47.                                                 Object[] parameters = new Object[]{
  48.                                                                 new String[]{"100","200","300"}
  49.                                                 };
  50.                                                 example2 = (Example_01) constructor.newInstance(parameters);
  51.                                         }
  52.                                 }
  53.                                 catch(Exception e){
  54.                                         System.out.println("在创建对象时出现异常,下面执行setAccessible()方法");
  55.                                         //设置为允许访问
  56.                                         constructor.setAccessible(true);
  57.                                 }
  58.                         }
  59.                         
  60.                         example2.print();
  61.                         System.out.println();
  62.                         
  63.                 }

  64.         }

  65. }
复制代码
在没加while抛出异常这段的时候运行正常,
结果为:
查看是否允许带有可变数量的参数:false
该构造方法的入口参数类型依次为:
该构造方法可能抛出的异常类型为:
查看是否允许带有可变数量的参数:false
该构造方法的入口参数类型依次为:
class java.lang.String
int
该构造方法可能抛出的异常类型为:
查看是否允许带有可变数量的参数:true
该构造方法的入口参数类型依次为:
class [Ljava.lang.String;
该构造方法可能抛出的异常类型为:
class java.lang.NumberFormatException



加上while抛出异常并输出相应值得这段以后,
无限运行出现结果:在创建对象时出现异常,下面执行setAccessible()方法
搞晕了,求解释

评分

参与人数 1技术分 +1 收起 理由
杜光 + 1 每天提问并回答问题,是对知识的复习和积累.

查看全部评分

2 个回复

正序浏览
本帖最后由 lkjghvcx@163.co 于 2013-7-19 15:54 编辑

         先调试一下:

                       Example_01 example2 = null;
                        while(example2 == null){
                                //如果该成员变量的访问权限为private,则抛出异常,即无法访问
                                constructor.setAccessible(true);     //放在前面,
                                try{
                                        //通过执行默认没有参数的构造方法创建对象
                                        if(i == 2)
                                                example2 = (Example_01) constructor.newInstance();

                                        //通过执行具有两个参数的构造方法创建对象
                                        else if(i == 1)
                                                example2 = (Example_01) constructor.newInstance("7",5);

                                        //通过执行具有可变数量参数的构造方法创建对象
                                        else{
                                                Object[] parameters = new Object[]{
                                                                new String[]{"100","200","300"}
                                                };
                                                example2 = (Example_01) constructor.newInstance(parameters);
                                        }
                                }
                                catch(Exception e){
//                                        System.out.println("在创建对象时出现异常,下面执行setAccessible()方法");
//                                        //设置为允许访问
//                                        constructor.setAccessible(true);
                                                e.printStackTrace();           //可以查看错误信息
                                }
                        }


错误信息:
java.lang.IllegalArgumentException              //参数错误
        at sun.reflect.GeneratedConstructorAccessor1.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)   
        at Reflect_Constructor.main(Reflect_Constructor.java:  )       example2 = (Example_01) constructor.newInstance(parameters);  这句出的错 //参数错误


考虑到 public Example_01(String...strings)throws NumberFormatException{  这个构造器可变参数是有问题的


因为private Example_01(){            
    }      私有的构造器
Example_01 example = new Example_01();  不可能这么调用的  new访问不到的private
所以new这句话调用的是public Example_01(String... strings)  构造器

public Example_01(String... strings)  构造器中
添加     System.out.println("开始调用构造器Example_01(String...  str)");
控制台会输出   开始调用构造器Example_01(String...  str)
所以new这句话调用的是public Example_01(String... strings)  构造器

为了让catch不无限循环 可以添加一句
System.exit(0);

是可变参数的问题;楼主改下试试                可变参数导致的混乱,








评分

参与人数 1技术分 +1 收起 理由
杜光 + 1 每天提问并回答问题,是对知识的复习和积累.

查看全部评分

回复 使用道具 举报
此处当f(i == 2) 时 Constructor constructor = declaredConstructors;返回的constructor是不是无参的构造方法,所以执行 example2 = (Example_01) constructor.newInstance();时肯定出问题。

同理当 i=1,都是错的。



你可以这样写他们的判断方式
Example_01 example2 = null;
while(example2 == null){                           
     try{   
       if(parameterTypes.length==0){
            example2 = (Example_01) constructor.newInstance();
       }
            else if(parameterTypes.length==2){
          example2 = (Example_01) constructor.newInstance("7",5);
       }
       else{
          Object[] parameters = new Object[]{
                                new String[]{"100","200","300"}
                                 };
          example2 = (Example_01) constructor.newInstance(parameters.toString());
      }
   }

catch(){}


评分

参与人数 1技术分 +1 收起 理由
杜光 + 1 每天提问并回答问题,是对知识的复习和积累.

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马