Java代表?

Java语言是否具有委托function,类似于C#如何支持委托?

不是真的,不是。

通过使用reflection来获得您可以调用的Method对象,您也许能够达到相同的效果,另一种方法是使用单个“invoke”或“execute”方法创build一个接口,然后实例化它们以调用方法你对(即使用匿名的内部类)感兴趣。

您可能还会发现这篇文章很有趣/有用: 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 } } 

然后,无论您在C#中使用SomeFunction委托,都可以使用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中,这些基本上变成了lambdaexpression式:

 // Java 8 SomeMethod(() -> { /* your implementation */ }); 

短篇小说:不 。

介绍

Microsoft Visual J ++开发环境的最新版本支持称为委托绑定方法引用的语言结构。 这个构造以及为支持它而引入的新的关键字delegatemulticast不属于Java TM编程语言的一部分,Java编程语言由Java语言规范指定,并且由JDKTM 1.1软件文档中包含的内部类规范 。

Java编程语言不太可能包含这个构造。 Sun已经认真考虑过在1996年采用这种技术,以至于build立和丢弃工作原型。 我们的结论是,绑定的方法引用是不必要的,不利于语言。 这个决定是在Borland International的协商下完成的,Borland International曾经在Delphi Object Pascal中使用绑定方法引用的经验。

我们相信绑定的方法引用是不必要的,因为另一个devise替代方法( 内部类 )提供了相同或更好的function 特别是,内部类完全支持用户界面事件处理的要求,并且已经被用于实现至less与Windows基础类一样全面的用户界面API。

我们认为绑定的方法引用是有害的,因为它们减less了Java编程语言的简单性和API的普遍面向对象的特性。 绑定的方法引用还将不规则性引入到语言语法和作用域规则中。 最后,他们稀释了对VM技术的投资,因为VM需要处理额外和不同types的引用和方法联系。

你读过这个 :

代表在基于事件的系统中是一个有用的构造。 基本上,委托是对指定对象上的方法分派进行编码的对象。 本文档展示了Java内部类如何为这些问题提供更一般的解决scheme。

什么是代表? 真的,它和C ++中使用的成员函数指针非常相似。 但是一个委托包含目标对象以及要调用的方法。 理想情况下,能够说:

obj.registerHandler(ano.methodOne);

..当某个特定的事件被收到时,方法methodOne将被调用。

这是代表结构实现的。

Java内部类

有人认为,Java通过内部类提供了这个function,因此不需要额外的Delegate结构。

 obj.registerHandler(new Handler() { public void handleIt(Event ev) { methodOne(ev); } } ); 

乍一看,这似乎是正确的,但同时也是一个滋扰。 因为对于许多事件处理示例,Delegates语法的简单性非常吸引人。

一般处理程序

但是,如果以更普遍的方式使用基于事件的编程,比如说,作为通用asynchronous编程环境的一部分,就存在更多的问题。

在这样的一般情况下,只包含目标方法和目标对象实例是不够的。 一般来说,可能还有其他的参数需要在事件处理程序注册时在上下文中确定。

在这种更一般的情况下,java方法可以提供一个非常优雅的解决scheme,特别是在与最终variables结合使用时:

 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); } } ); } 

决赛*决赛*决赛

得到你的关注?

请注意,最终variables可以从匿名类方法定义中访问。 一定要仔细研究这些代码,以了解后果。 这可能是一个非常强大的技术。 例如,在MiniDOM中注册处理程序和更一般的情况下,可以使用它。

相比之下,代表结构并没有为这个更一般的要求提供解决scheme,因此应该被拒绝,作为devise基础的一个习惯用语。

我知道这个post是旧的,但是Java 8已经添加了lambdaexpression式,以及一个function接口的概念,这个接口只有一个方法。 这些一起提供了与C#代表类似的function。 在这里看到更多的信息,或只是谷歌Java Lambdas。 http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html

不,但是他们使用代理和reflection来伪造:

  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<TestClass, Callable<String>> knockKnockDelegator = Delegator.ofMethod("knockKnock") .of(TestClass.class) .to(Callable.class); Callable<String> callable = knockKnockDelegator.delegateTo(testInstance); assertThat(callable.call(), is("who's there?")); } 

关于这个习惯用法的好处是你可以在你创build委托的地方validation委托方法是否存在,并且具有所需的签名(虽然不是在编译时,不幸的是,尽pipeFindBugs插件可能帮助这里),然后安全地使用它委托给各种实例。

查看github上的karg代码以获取更多testing和实现 。

我已经使用reflection在Java中实现了callback/委托支持。 细节和工作来源可以在我的网站上find 。

怎么运行的

有一个名为Callback的原则类,它带有一个名为WithParms的嵌套类。 需要callback的API将一个Callback对象作为参数,如果需要的话,创build一个Callback.WithParms作为方法variables。 由于这个对象的很多应用都是recursion的,所以这个工作非常干净。

性能仍然是我的首要任务,我不希望被要求创build一个一次性的对象数组来保存每个调用的参数 – 毕竟在一个大型的数据结构中可能有成千上万的元素,并在一个消息处理我们最终可能会每秒处理数千个数据结构。

为了成为线程安全的参数数组需要唯一地存在于API方法的每个调用中,并且为了效率,每次调用callback都应该使用同一个参数; 我需要第二个对象,这将创build便宜,以便绑定与调用参数数组的callback。 但是,在某些情况下,由于其他原因,调用者将已经拥有参数数组。 由于这两个原因,参数数组不属于callback对象。 另外,调用的select(将参数作为数组或单个对象传递)属于API的使用callback,使其能够使用哪个调用最适合其内部工作。

WithParms嵌套类是可选的,它有两个目的,它包含callback调用所需的参数对象数组,它提供了10个重载的invoke()方法(有1到10个参数),它们加载参数数组,然后调用callback目标。

以下是使用callback处理目录树中的文件的示例。 这是一个初始的validation过程,它只计算要处理的文件,并确保没有超过预定的最大大小。 在这种情况下,我们只需使用API​​调用内联创buildcallback。 但是,我们将目标方法反映为一个静态值,所以每次都不会进行reflection。

 static private final Method COUNT =Callback.getMethod(Xxx.class,"callback_count",true,File.class,File.class); ... IoUtil.processDirectory(root,new Callback(this,COUNT),selector); ... private void callback_count(File dir, File fil) { if(fil!=null) { // file is null for processing a directory fileTotal++; if(fil.length()>fileSizeLimit) { throw new Abort("Failed","File size exceeds maximum of "+TextUtil.formatNumber(fileSizeLimit)+" bytes: "+fil); } } progress("Counting",dir,fileTotal); } 

IoUtil.processDirectory():

 /** * Process a directory using callbacks. To interrupt, the callback must throw an (unchecked) exception. * Subdirectories are processed only if the selector is null or selects the directories, and are done * after the files in any given directory. When the callback is invoked for a directory, the file * argument is null; * <p> * The callback signature is: * <pre> void callback(File dir, File ent);</pre> * <p> * @return The number of files processed. */ static public int processDirectory(File dir, Callback cbk, FileSelector sel) { return _processDirectory(dir,new Callback.WithParms(cbk,2),sel); } static private int _processDirectory(File dir, Callback.WithParms cbk, FileSelector sel) { int cnt=0; if(!dir.isDirectory()) { if(sel==null || sel.accept(dir)) { cbk.invoke(dir.getParent(),dir); cnt++; } } else { cbk.invoke(dir,(Object[])null); File[] lst=(sel==null ? dir.listFiles() : dir.listFiles(sel)); if(lst!=null) { for(int xa=0; xa<lst.length; xa++) { File ent=lst[xa]; if(!ent.isDirectory()) { cbk.invoke(dir,ent); lst[xa]=null; cnt++; } } for(int xa=0; xa<lst.length; xa++) { File ent=lst[xa]; if(ent!=null) { cnt+=_processDirectory(ent,cbk,sel); } } } } return cnt; } 

这个例子说明了这种方法的美妙之处 – 特定于应用程序的逻辑被抽象为callback函数,recursion地遍历目录树的苦差事被很好地放在一个完全可重用的静态工具方法中。 而且我们不必为每次使用而重复定义和实现接口的价格。 当然,一个接口的参数是关于什么是实现(它是强制的,而不是简单的文档),它是更加明确的 – 但在实践中,我没有发现它是一个问题得到callback定义的权利。

定义和实现一个接口并不是那么糟糕(除非你像我一样分发小程序,避免创build额外的类实际上很重要),但是真正发光的是当你在一个类中有多个callback。 不仅被迫将它们分别推入到一个单独的内部类中,而且在已部署的应用程序中增加了开销,但编程完全枯燥乏味,而所有这些锅炉代码实际上只是“噪声”。

尽pipe它几乎没有干净,但是您可以使用Java 代理来实现类似于C#委托的function。

不,但内部也有类似的行为。

在C#中,委托用于创build一个单独的入口点,它们的工作方式类似于函数指针。

在Java中,没有东西作为函数指针(上面看),但内部Java需要做同样的事情,以实现这些目标。

例如,在Java中创build线程需要扩展Thread的类或实现Runnable,因为类对象variables可以用作内存位置指针。

是&否,但是Java中的委托模式可以这样想。 这个video教程是关于活动片段之间的数据交换,它使用接口具有委托sorting模式的很好的本质。

Java接口

Java没有代表,并为此感到自豪:)。 从我在这里读到的,我发现了两种伪造代表的方式:1.反思; 内心的课堂

思考是slooooow! 内部类不包含最简单的用例:sort函数。 不想进入细节,但具有内部类的解决scheme基本上是创build一个整数数组的包装类,以升序sorting和一个整数数组的类按降序sorting。