V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cqdx02
V2EX  ›  程序员

请教一个 Java 反射与动态代理的问题:动态代理生成的对象通过反射设置报错

  •  
  •   cqdx02 · 2020-10-20 00:23:21 +08:00 · 1300 次点击
    这是一个创建于 1283 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如定义了一个接口 IHello:

    interface IHello {
    
    	void printHello();
    }
    

    以及一个 User 类:

    class User {
    
      IHello ihello;
    
      public User(){}
    
      public void setIHello(IHello hello){
    
        this.ihello = hello;
      }
    
      public void sayHello(){
    
        iHello.printHello();
      }
    
    }
    

    在实际调用时,采用动态代理先生产 IHello 的实例,然后设置到 User 对象中调用是可以的:

    Ihello hello = (IHello) new DynamicProxy().bind(new Hello());
    
    User user = new User();
    
    user.setIHello(hello);
    
    user.sayHello();
    

    现在某些情况下,我要通过反射的方式设置 User 中的成员变量,我是这么写的:

    Ihello hello = (IHello) new DynamicProxy().bind(new Hello());
    
    User user = new User();
    
    Class<?> parmeter = new Class[1];
    
    parmeter[0] = hello.getClass();
    
    // 获取方法时出错
    
    Method setHello = user.getClass().getDeclaredMethod("setIHello", parmeter);
    
    setHello.invoke(user,hello);
    

    在上面一句获取方法时出错了,报错内容为 NoSuchMethodException,因为 parmeter 类型不对。

    请教应该怎么改呢?

    (上面那句改成 getDeclaredMethod("setIHello", IHello.class)肯定是可以的,问题是现在不希望指定类型,而希望 parmeter 是动态生成的)

    7 条回复    2020-10-20 09:39:21 +08:00
    JasonLaw
        1
    JasonLaw  
       2020-10-20 07:18:18 +08:00 via iPhone
    hello.getClass() != IHello.class
    cqdx02
        2
    cqdx02  
    OP
       2020-10-20 08:42:44 +08:00 via Android
    @JasonLaw 嗯嗯,那应该如何改呢?
    JasonLaw
        3
    JasonLaw  
       2020-10-20 08:48:42 +08:00
    @cqdx02 #2 我希望你提供完整的代码,你贴出的代码不仅仅有错误、不完整,也不知道 DynamicProxy 到底是哪里来的。
    cqdx02
        4
    cqdx02  
    OP
       2020-10-20 09:12:37 +08:00 via Android
    @JasonLaw 好的,我只贴了报错的那部分,晚上回去补全下。
    young1lin
        5
    young1lin  
       2020-10-20 09:33:22 +08:00
    你这样写肯定是错的啊,会不会用反射? IDEA 没提示?

    parmeter[0] = hello.getClass();

    // 获取方法时出错

    Method setHello = user.getClass().getDeclaredMethod("setIHello", parmeter);
    首先,你这获取的是具体的实体类,但是这里是要求你根据方法名和方法参数类型,来获得具体的方法对象句柄。你也可以理解为获得方法的定义,方法的外壳。

    后面的 method.invoke 是传具体参数,如果你这里传的是 hello.getClass() 这里获取的是具体的类,比如 Hello.class,而不是 IHello.class 。

    你可以打个断点看看到底是怎么回事,他就会去找 setIHello(Hello hello),而不是 setIHello(IHello iHello)方法,当然会报没有这样的方法的错误。你把这个

    Method setHello = user.getClass().getDeclaredMethod("setIHello", parmeter);

    parrmeter 改成 IHello.class 不就好了?

    我建议你好好在 《 Java 编程思想》里面好好看看关于反射的那一章。
    palmers
        6
    palmers  
       2020-10-20 09:38:55 +08:00
    // 获取方法时出错

    Method setHello = user.getClass().getDeclaredMethod("setIHello", parmeter);
    palmers
        7
    palmers  
       2020-10-20 09:39:21 +08:00
    @palmers 这句使用泛型约束是可以的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5190 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 09:23 · PVG 17:23 · LAX 02:23 · JFK 05:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.