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

有关 Java 反射机制 invoke 方法参数的疑问

  •  
  •   onice · 2016-03-02 22:38:24 +08:00 · 4150 次点击
    这是一个创建于 3189 天前的主题,其中的信息可能已经有所发展或是发生改变。

    手册中的 invoke 方法描述是这样子的:
    public Object invoke(Object obj,
    Object... args)
    throws IllegalAccessException,
    IllegalArgumentException,
    InvocationTargetException

    为什么执行方法非要传一个 obj 对象?

    我写了个例子:

    public class Test01 {
    
        public void m01(String info){
            System.out.println(info);
        }
    }
    
    public class Reflect {
    
        public static void main(String[] args) {
            try {
                Method method = Class.forName("com.hack4b.test.Father").getMethod("m01", String.class);
                //method.invoke(?, "Hello");  //问号里的参数为 null 会错误
            } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    

    我只想通过反射机制调用 Test 类的 m01 方法,并传参字符串 Hello 给 info ,然后通过 m01 方法打印出来。

    我一直困惑, invoke 方法第一个参数到底是干什么用的?要执行方法,直接传参数被调用方法的参数就好了啊?为什么还要在第一个参数加一个 Object 类型的对象?

    手册上是这么解释的:

    Parameters:
    obj - the object the underlying method is invoked from
    args - the arguments used for the method call

    看上去,意思是 obj 是调用方法的对象,也就是说指明是哪一个对象去调用方法。

    我写的例子中,我是在 main 方法中通过反射机制获取的 m01 方法并执行,按照上述的意思,我是想用当前对象去调用 m01 方法,于是我就传了个 this 进去,结果 IDE 提示语法错误: Cannot use this in a static context

    然后我又声明了一个 Object 对象传进去,程序也没法跑,还抛异常: java.lang.IllegalArgumentException: object is not an instance of declaring class

    难道是我没理解对?

    6 条回复    2016-03-03 08:28:43 +08:00
    onice
        1
    onice  
    OP
       2016-03-02 22:42:50 +08:00
    补充下, Test01 类之前的名字叫 Father ,所以下面的 main 方法注册的类是 Father 。
    slixurd
        2
    slixurd  
       2016-03-02 22:52:28 +08:00
    在 static main 方法里面哪里来的 this 。。。
    你肯定写错了。。。
    传入 obj 就是为了让特定对象调用那个 method 而已,如果是 static 方法可以传 null
    java.lang.IllegalArgumentException: object is not an instance of declaring class
    这个 Error 就更明确了,传错对象了。。。
    angelface
        3
    angelface  
       2016-03-02 22:52:46 +08:00
    蛤蛤蛤蛤
    bin456789
        4
    bin456789  
       2016-03-02 22:53:39 +08:00
    obj 参数是 Test01 实例
    incompatible
        5
    incompatible  
       2016-03-02 23:25:45 +08:00
    你的 m01()方法并不是 static 的,所以对它的调用需要基于 Test01 类的某个实例。
    比如你得先 Test01 t01 = new Test01();后才能用 t01.m01(),而不能直接用 Test01.m01()。

    反射时也是同理啊,你获得的 m01 这个 method 的 invoke 方法的第一个参数,应该传一个 Test01 类的实例进去。


    如果想让你的代码能跑通,你只要把 m01()改成 static 的就行了。
    onice
        6
    onice  
    OP
       2016-03-03 08:28:43 +08:00
    @bin456789 @incompatible @slixurd 拿到 Test01 类之后,通过 newInstance()方法获得的实例,把这个传进去就成功了。原来 obj 是被调方法类的实例,现在我明白了。感谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3417 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:48 · PVG 19:48 · LAX 03:48 · JFK 06:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.