Java的Method ≈ C/C++的函数指针 
Java的Method ≈ C#的delegate 我们姑且将三者统称为“函数指针”。函数指针被用来实现一个叫做“回调”的功能。即,将Method或delegate或函数指针作为参数传给另一个函数,
被传参的函数调用一个函数的指针实现相应的功能。
我不禁感到疑惑:有必要用函数指针吗?或者说,为什么要用函数指针?
Java是面向对象的语言,所有的方法属于类或对象。那么,完全可以不用函数指针,
直接在一个函数里,SomeClass.SomeFunction(Object[] para); 调用不就行了?
为什么还要拐弯抹角地把函数打包成指针,然后传函数指针,再在方法体中调用函数指针呢?

解决方案 »

  1.   

    如果没有这个东西,打个最简单的比方,在struts2.0中继承自ActionSupport的类,就只能用execute方法。而实际上我们可以自己随便任意命名一个方法,只要不带参数,返回值是String,然后在xml中配置好方法名就可以了。在这种地方就必须要例如Method,否则你肯定没有办法实现上面的功能。Method主要用在动态调用方法上,就是说在编译的时候并不知道需要调用哪个函数的情况下,虽然这种方法不是很好,但是对于程序代码有时候采用这种方法可以减少很多的类。
      

  2.   

    SomeClass.SomeFunction(Object[] para); 你这是静态方法的调用,java中的Method就是c/c++中的函数(Function),不知你为什么把函数指针扯进来,还好你没说指针函数
      

  3.   


    谢谢你的回答。我不懂Struts,对Method和“回调”也是一头雾水。我就不明白,为什么在编译时会不知道调用哪个函数呢?代码当中应该写明了调用哪个方法的。即便是Method,它也是指向一个具体的函数,Method在创建时一定是和这个具体的函数绑定在一起。如果没有绑定在一起,someMethod.invoke(Object obj, Object[] para)怎么知道应该调用哪个函数?它的参数和它指向的函数应该是一一对应的吧。不知道调哪个函数怎么可能做到一一对应呢?
      

  4.   


    这里的SomeClass可以是静态调用也可以是具体对象的调用。Java中的Method是C/C++中的函数?那Java的函数又对应C/C++的什么概念呢? 我不是不懂Method的用法,它其实就是C/C++的函数指针。当然用C/C++的术语去硬套Java的概念是不妥的,但“回调”这个概念是C/C++,Java中所共有的。C/C++实现“回调”的(似乎是)唯一的方法就是“函数指针”。Java里可以用Method实现。原理是一样的,但我就是不理解。
      

  5.   

    java的method对象不是c/c++的函数指针,无论从概念,内存存储方式,调用执行方式上都不同,只是作用上相似而已。不要把java的method对象与函数指针混为一谈。
    java的对象句柄确实可以实现为一个内存指针,但是method对象句柄并不是指向c/c++里面的函数。
    想要理解Method对象的使用,学习java的反射机制即可理解,但是绝对不要把它跟C/C++函数混淆起来,他们只是功能相似而已。
      

  6.   


    我对于反射机制的理解:在运行时识别对象的类型,然后完成相应的操作。典型用法就是if(someObject.getClass() == someClass) 
        ((someClassType)someObject).doSomething();
    不过这个和Method和“回调”有何关系?Method不会在运行时不知道它所指向的具体函数的。
      

  7.   

    你根本没有了解反射,去了解了解吧,你那种太肤浅了。
    反射的包都在java.lang.reflection包下,光用到java.lang.Class类不算用到反射。
      

  8.   


    能不能请您不肤浅地解释一下“回调”和Method的关系?
      

  9.   

    而且你的那种用法也有错误,那种代码最好写成
    if(obj instanceof MyClassOrInteface){
        ((MyClassOrInteface)obj).dosomething();
    }
    因为obj经常可能是MyClassOrInteface的子类所生成的实例,而不是这个类的实例。
      

  10.   


    受教了。请再接再厉解释一下Method,谢谢!
      

  11.   

    称作函数指针并不合适,因为她不是函数指针.其意义并不相同.这个特性叫做自省,也就是知道自己的结构.这种调用的技术叫做反射.这是从编译之后的元数据中获得的调用接口,使用时可以通过函数名来匹配.这个的意义远比函数指针深远,函数指针并不是自省.函数指针仅仅是一个代码的指针.执行的时候跳过去.而反射不同,他依赖于自省的特性,也就是从对象可以查到类的元数据.这样给以后智能处理也留下了空间.至于callback--回调这个东西.曾经有过血泪史.当年学c/c++的时候,发现callback并不是一个关键字,也不是保留字.最后几经追查,发现这个东西是一个宏,在预处理的时候被替换成std或__std什么的.这两个东西是c/c++的保留字,即便不写也会默认加在函数前面的修饰字.意义在于说明调用方式,也就是长格式,压栈方式什么的.所谓的callback仅仅是一个逻辑上的标识,表示这个函数并不是在代码中直接调用,而是靠消息或其他时间发生的时候出发,然后由系统或程序选择调用.最重要的不同就是函数指针需要在代码中明确声明,否则你没法获得函数的位置的.而java得自省特性及衍生的反射技术,可以通过类名或函数名等字符串资源作为值.这就使得程序运行逻辑,可以依赖外部配置资源而运行.所以,这个技术在java中很受喜爱.
      

  12.   

    你只是想理解回调的话,网络上也有很多资料的,而且讲也会长篇大论。我这里只是做个简单的阐述。
    这牵扯到一个语言的动态性问题。譬如说一个函数A调用另外一个函数B的时候,函数A只关心B能够做什么,而不关心B怎么做,即是对于A函数来说往B中放入一个值,然后B做了操作以后返回一个值既可以了,其它不关心B是怎么把这个值得出来的。但是如果在函数A中只写死调用B的花,虽然A函数不关心B的调用方式,但是A必须使用B的方式来调用,但是这个时候有个函数C同样能够完成功能,而且C的实现比B要好(效率高等等),这个时候A想调用C就不得不更改代码,把B的调用改为C调用了,可惜过了一阵子又出现D函数了,这样改来该去就会需要一种实现,如果B、C、D这三种实现方式以参数的方式传给A来调用,这样就可以灵活更换实现方式而不用改代码了。这就是函数的回调了。至于回调为什么跟Method对象有关系,只要你了解了反射你就能理解了,Method对象映射了方法区中的方法,怎么使用学习反射的使用就会了,反射不难的。
      

  13.   


    回调函数被以“函数指针”的方式调用(C/C++),在Java里的形式就是someMethod.invoke(Object obj, Object[] para)。不论是直接还是间接调用,someMethod所对应的回调函数还是被调用了。既然一个回调函数是一段代码,那么就可以显式地通过SomeClass.doSomething(Object[] para)或someObject.doSomething(Object[] para)直接调用,看不出有什么特别的理由非要通过回调间接地调用。
    就好比,你有一本书要送给你隔壁邻居,你明明可以上他家直接给他,但偏偏要搞个包裹用EMS邮寄给他。费时费钱,你邻居还不见得感谢你。我觉得回调机制就是一种拐弯抹角的技术,看不出有什么必要使用。
      

  14.   

    那么就可以显式地通过SomeClass.doSomething(Object[] para)或someObject.doSomething(Object[] para)直接调用,看不出有什么特别的理由非要通过回调间接地调用。 
    这样是因为可能方法名是动态的,例如Hibernate从数据库Load数据后,需要调用bean.setXXX方法将值传入对象中,但是这些属性名称是动态的,而不是固定的所以需要类似于Method m = getClass().getMethod("set" + propName, new Class[]{propType});
    这样来动态获取m,然后才可以m.invoke调用
    java.lang.reflect的主要作用都是为了在运行的过程中动态调用方法属性等,而不是在编译时已经固定好