Java语言是否具有委托功能,类似于C#如何支持委托?
不是,不是.
您可以通过使用反射获取然后可以调用的Method对象来实现相同的效果,另一种方法是使用单个"invoke"或"execute"方法创建一个接口,然后实例化它们以调用该方法你感兴趣的(即使用匿名的内部类).
您可能还会发现这篇文章有趣/有用:Java程序员看C#代表
根据您的意思,您可以使用策略模式实现类似的效果(传递方法).
而不是像这样的行声明一个命名的方法签名:
// C# public delegate void SomeFunction();
声明一个接口:
// Java public interface ISomeBehaviour { void SomeFunction(); }
对于方法的具体实现,定义一个实现该行为的类:
// Java public class TypeABehaviour implements ISomeBehaviour { public void SomeFunction() { // TypeA behaviour } } public class TypeBBehaviour implements ISomeBehaviour { public void SomeFunction() { // TypeB behaviour } }
然后,无论你SomeFunction
在C#中拥有一个委托,只需使用一个ISomeBehaviour
引用:
// C# SomeFunction doSomething = SomeMethod; doSomething(); doSomething = SomeOtherMethod; doSomething(); // Java ISomeBehaviour someBehaviour = new TypeABehaviour(); someBehaviour.SomeFunction(); someBehaviour = new TypeBBehaviour(); someBehaviour.SomeFunction();
使用匿名内部类,您甚至可以避免声明单独的命名类,并且几乎将它们视为真正的委托函数.
// Java public void SomeMethod(ISomeBehaviour pSomeBehaviour) { ... } ... SomeMethod(new ISomeBehaviour() { @Override public void SomeFunction() { // your implementation } });
这应该仅在实现非常特定于当前上下文时使用,并且不会从重用中受益.
然后当然在Java 8中,这些基本上变成了lambda表达式:
// Java 8 SomeMethod(() -> { /* your implementation */ });
短篇小说:不.
介绍最新版本的Microsoft Visual J ++开发环境支持称为委托或绑定方法引用的语言构造.此构造以及为支持它
delegate
而multicast
引入的新关键字不是Java TM 编程语言的一部分,Java语言规范由Java语言规范指定,并由JDKTM 1.1软件文档中包含的内部类规范进行修改.Java编程语言不太可能包含此构造.Sun已经仔细考虑过在1996年采用它,以建立和丢弃工作原型.我们的结论是绑定方法引用是不必要的并且对语言有害.该决定是在与Borland International协商后做出的,Borland International曾在Delphi Object Pascal中使用绑定方法引用.
我们认为绑定方法引用是不必要的,因为另一种设计选择,内部类,提供相同或更高的功能.特别是,内部类完全支持用户界面事件处理的要求,并且已经用于实现至少与Windows Foundation Classes一样全面的用户界面API.
我们认为绑定方法引用是有害的,因为它们有损于Java编程语言的简单性和API的普遍面向对象特性.绑定方法引用还会在语言语法和作用域规则中引入不规则性.最后,它们稀释了对VM技术的投资,因为VM需要有效地处理额外的和不同类型的引用和方法链接.
你读过这个:
代表是基于事件的系统中的有用构造.基本上,Delegates是对指定对象上的方法分派进行编码的对象.本文档展示了java内部类如何为这些问题提供更通用的解决方案.
什么是代表?实际上它非常类似于C++中使用的指向成员函数的指针.但是委托包含目标对象以及要调用的方法.理想情况下,能够说:
obj.registerHandler(ano.methodOne);
..并且当收到某个特定事件时,方法methodOne将在ano上调用.
这就是委托结构所实现的目标.
Java内部类
有人认为Java通过匿名内部类提供此功能,因此不需要额外的Delegate构造.
obj.registerHandler(new Handler() { public void handleIt(Event ev) { methodOne(ev); } } );
乍一看,这似乎是正确的,但同时也是一种麻烦.因为对于许多事件处理示例,Delegates语法的简单性非常有吸引力.
通用处理程序
但是,如果以更普遍的方式使用基于事件的编程,例如,作为一般异步编程环境的一部分,则存在更多的利害关系.
在这种一般情况下,仅包括目标方法和目标对象实例是不够的.通常,可能存在所需的其他参数,这些参数在注册事件处理程序时在上下文中确定.
在这种更一般的情况下,java方法可以提供非常优雅的解决方案,特别是与最终变量的使用相结合时:
void processState(final T1 p1, final T2 dispatch) { final int a1 = someCalculation(); m_obj.registerHandler(new Handler() { public void handleIt(Event ev) { dispatch.methodOne(a1, ev, p1); } } ); }
最后*决赛*决赛
你注意了吗?
请注意,可以从匿名类方法定义中访问最终变量.请务必仔细研究此代码以了解其后果.这可能是一种非常强大的技术.例如,在MiniDOM中注册处理程序时以及更一般的情况下,它可以用于很好的效果.
相比之下,Delegate结构并没有为这个更一般的要求提供解决方案,因此应该作为设计可以基于的习语被拒绝.
我知道这篇文章很老,但Java 8添加了lambdas,以及功能接口的概念,这是任何只有一种方法的接口.它们共同提供与C#代理类似的功能.有关详细信息,请参阅此处,或者只是google Java Lambdas. http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html
不,但他们使用代理和反射是可伪造的:
public static class TestClass { public String knockKnock() { return "who's there?"; } } private final TestClass testInstance = new TestClass(); @Test public void can_delegate_a_single_method_interface_to_an_instance() throws Exception { Delegator> knockKnockDelegator = Delegator.ofMethod("knockKnock") .of(TestClass.class) .to(Callable.class); Callable callable = knockKnockDelegator.delegateTo(testInstance); assertThat(callable.call(), is("who's there?")); }
关于这个习惯用法的好处是,您可以在创建委托者的位置验证委托方法是否存在,并且具有所需的签名(尽管不是在编译时,但遗憾的是,虽然FindBugs插件可能帮助这里),然后安全地使用它委托给各种实例.
有关更多测试和实现,请参阅github上的karg代码.