Java的Method ≈ C/C++的函数指针
Java的Method ≈ C#的delegate 我们姑且将三者统称为“函数指针”。函数指针被用来实现一个叫做“回调”的功能。即,将Method或delegate或函数指针作为参数传给另一个函数,
被传参的函数调用一个函数的指针实现相应的功能。
我不禁感到疑惑:有必要用函数指针吗?或者说,为什么要用函数指针?
Java是面向对象的语言,所有的方法属于类或对象。那么,完全可以不用函数指针,
直接在一个函数里,SomeClass.SomeFunction(Object[] para); 调用不就行了?
为什么还要拐弯抹角地把函数打包成指针,然后传函数指针,再在方法体中调用函数指针呢?
Java的Method ≈ C#的delegate 我们姑且将三者统称为“函数指针”。函数指针被用来实现一个叫做“回调”的功能。即,将Method或delegate或函数指针作为参数传给另一个函数,
被传参的函数调用一个函数的指针实现相应的功能。
我不禁感到疑惑:有必要用函数指针吗?或者说,为什么要用函数指针?
Java是面向对象的语言,所有的方法属于类或对象。那么,完全可以不用函数指针,
直接在一个函数里,SomeClass.SomeFunction(Object[] para); 调用不就行了?
为什么还要拐弯抹角地把函数打包成指针,然后传函数指针,再在方法体中调用函数指针呢?
谢谢你的回答。我不懂Struts,对Method和“回调”也是一头雾水。我就不明白,为什么在编译时会不知道调用哪个函数呢?代码当中应该写明了调用哪个方法的。即便是Method,它也是指向一个具体的函数,Method在创建时一定是和这个具体的函数绑定在一起。如果没有绑定在一起,someMethod.invoke(Object obj, Object[] para)怎么知道应该调用哪个函数?它的参数和它指向的函数应该是一一对应的吧。不知道调哪个函数怎么可能做到一一对应呢?
这里的SomeClass可以是静态调用也可以是具体对象的调用。Java中的Method是C/C++中的函数?那Java的函数又对应C/C++的什么概念呢? 我不是不懂Method的用法,它其实就是C/C++的函数指针。当然用C/C++的术语去硬套Java的概念是不妥的,但“回调”这个概念是C/C++,Java中所共有的。C/C++实现“回调”的(似乎是)唯一的方法就是“函数指针”。Java里可以用Method实现。原理是一样的,但我就是不理解。
java的对象句柄确实可以实现为一个内存指针,但是method对象句柄并不是指向c/c++里面的函数。
想要理解Method对象的使用,学习java的反射机制即可理解,但是绝对不要把它跟C/C++函数混淆起来,他们只是功能相似而已。
我对于反射机制的理解:在运行时识别对象的类型,然后完成相应的操作。典型用法就是if(someObject.getClass() == someClass)
((someClassType)someObject).doSomething();
不过这个和Method和“回调”有何关系?Method不会在运行时不知道它所指向的具体函数的。
反射的包都在java.lang.reflection包下,光用到java.lang.Class类不算用到反射。
能不能请您不肤浅地解释一下“回调”和Method的关系?
if(obj instanceof MyClassOrInteface){
((MyClassOrInteface)obj).dosomething();
}
因为obj经常可能是MyClassOrInteface的子类所生成的实例,而不是这个类的实例。
受教了。请再接再厉解释一下Method,谢谢!
这牵扯到一个语言的动态性问题。譬如说一个函数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对象映射了方法区中的方法,怎么使用学习反射的使用就会了,反射不难的。
回调函数被以“函数指针”的方式调用(C/C++),在Java里的形式就是someMethod.invoke(Object obj, Object[] para)。不论是直接还是间接调用,someMethod所对应的回调函数还是被调用了。既然一个回调函数是一段代码,那么就可以显式地通过SomeClass.doSomething(Object[] para)或someObject.doSomething(Object[] para)直接调用,看不出有什么特别的理由非要通过回调间接地调用。
就好比,你有一本书要送给你隔壁邻居,你明明可以上他家直接给他,但偏偏要搞个包裹用EMS邮寄给他。费时费钱,你邻居还不见得感谢你。我觉得回调机制就是一种拐弯抹角的技术,看不出有什么必要使用。
这样是因为可能方法名是动态的,例如Hibernate从数据库Load数据后,需要调用bean.setXXX方法将值传入对象中,但是这些属性名称是动态的,而不是固定的所以需要类似于Method m = getClass().getMethod("set" + propName, new Class[]{propType});
这样来动态获取m,然后才可以m.invoke调用
java.lang.reflect的主要作用都是为了在运行的过程中动态调用方法属性等,而不是在编译时已经固定好