2025-02-11 07:00:05

Java代表?

Java语言是否具有委托特性,类似于c#对委托的支持?


当前回答

所描述的代码提供了c#委托的许多优点。方法,无论是静态的还是动态的,都可以以统一的方式处理。通过反射调用方法的复杂性降低了,而且代码是可重用的,因为在用户代码中不需要额外的类。请注意,我们调用的是invoke的另一个方便版本,其中只带一个参数的方法可以在不创建对象数组的情况下被调用。

  class Class1 {
        public void show(String s) { System.out.println(s); }
    }

    class Class2 {
        public void display(String s) { System.out.println(s); }
    }

    // allows static method as well
    class Class3 {
        public static void staticDisplay(String s) { System.out.println(s); }
    }

    public class TestDelegate  {
        public static final Class[] OUTPUT_ARGS = { String.class };
        public final Delegator DO_SHOW = new Delegator(OUTPUT_ARGS,Void.TYPE);

        public void main(String[] args)  {
            Delegate[] items = new Delegate[3];

            items[0] = DO_SHOW .build(new Class1(),"show,);
            items[1] = DO_SHOW.build (new Class2(),"display");
            items[2] = DO_SHOW.build(Class3.class, "staticDisplay");

            for(int i = 0; i < items.length; i++) {
                items[i].invoke("Hello World");
            }
        }
    }

其他回答

通过类路径上的安全镜像,你可以得到类似c#委托和事件的东西。

来自项目README的例子:

Java中的委托!

  Delegate.With1Param<String, String> greetingsDelegate = new Delegate.With1Param<>();
  greetingsDelegate.add(str -> "Hello " + str);
  greetingsDelegate.add(str -> "Goodbye " + str);

  DelegateInvocationResult<String> invocationResult = 
  greetingsDelegate.invokeAndAggregateExceptions("Sir");

  invocationResult.getFunctionInvocationResults().forEach(funInvRes -> 

  System.out.println(funInvRes.getResult()));
  //prints: "Hello sir" and "Goodbye Sir"

事件

  //Create a private Delegate. Make sure it is private so only *you* can invoke it.
  private static Delegate.With0Params<String> trimDelegate = new Delegate.With0Params<>();

  //Create a public Event using the delegate you just created.
  public static Event.With0Params<String> trimEvent= new Event.With0Params<>(trimDelegate)

看看这个SO的答案。

没有,没有。

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

你可能还会发现这篇文章很有趣/有用:一个Java程序员看c#委托(@blueskyprojects.com)

虽然它远没有那么干净,但您可以使用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中,这些基本变成了lambda表达式:

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

不,但它内部有相似的行为。

在c#中,委托用于创建一个单独的入口点,它们的工作原理很像函数指针。

在java中没有函数指针,但是在内部java需要做同样的事情来实现这些目标。

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