Java中类似于C#匿名方法的东西是什么?

30

在C#中,您可以匿名定义委托(即使它们只是语法糖)。例如,我可以这样做:

public string DoSomething(Func<string, string> someDelegate)
{
     // Do something involving someDelegate(string s)
} 

DoSomething(delegate(string s){ return s += "asd"; });
DoSomething(delegate(string s){ return s.Reverse(); });

在Java中是否可以传递像这样的代码?我正在使用processing框架,该框架使用相当旧的Java版本(不支持泛型)。


Java中委托的一般问题 - nawfal
6个回答

61

Java 8之前:

在Java中,最接近委托的方式是通过单方法接口和匿名内部类实现。

interface StringFunc {
   String func(String s);
}

void doSomething(StringFunc funk) {
   System.out.println(funk.func("whatever"));
}

doSomething(new StringFunc() {
      public String func(String s) {
           return s + "asd";
      }
   });


doSomething(new StringFunc() {
      public String func(String s) {
           return new StringBuffer(s).reverse().toString();
      }
   });

Java 8及以上版本:

Java 8为该语言添加了Lambda表达式。

    doSomething((t) -> t + "asd");
    doSomething((t) -> new StringBuilder(t).reverse().toString());

2
[Google Collections][1]和Groovy[2]可能会引起您的兴趣。[1] http://code.google.com/p/google-collections/ [2] http://groovy.codehaus.org/ - Michael Lloyd Lee mlk

13

虽然不完全相同,但是Java有类似的东西。

它被称为匿名内部类(anonymous inner classes)。

让我给你举个例子:

DoSomething(new Runnable() {
   public void run() {
       // "delegate" body
   }
});

这需要更多的文字说明并要求实现一个接口,但除此之外,它基本上与原来的东西一样。


4

使用匿名内部类,在Java中,您的示例代码看起来应该像这样:

interface Func {
    String execute(String s);
}

public String doSomething(Func someDelegate) {
    // Do something involving someDelegate.execute(String s)
}

doSomething(new Func() { public String execute(String s) { return s + "asd"; } });
doSomething(new Func() { public String execute(String s) { return new StringBuilder(s).reverse().toString(); } } });

3

在Java中是否可以像这样传递代码?我正在使用processing框架,它有一个非常旧的Java版本(没有泛型)。

由于问题是关于Processing特定答案的,所以没有直接的等价物。但是Processing使用Java 1.4语言级别,而Java 1.1引入了匿名内部类,这是一个粗略的近似。


3
例如:

举个例子:

public class Delegate
{
    interface Func
    {
        void execute(String s);
    }

    public static void doSomething(Func someDelegate) {
        someDelegate.execute("123");
    }

    public static void main(String [] args)
    {

        Func someFuncImplementation = new Func() 
        {
            @Override
            public void execute(String s) {
                System.out.println("Bla Bla :"  + s);
            }
        };

        Func someOtherFuncImplementation = new Func() 
        {
            @Override
            public void execute(String s) {
                System.out.println("Foo Bar:"  + s);
            }
        };


        doSomething(someFuncImplementation);
        doSomething(someOtherFuncImplementation);
    }
}

输出:

某某:123

某某:123


0

你们都忘记了,C#委托首先是线程安全的。 这些示例仅适用于单线程应用程序。

大多数现代应用程序都是基于多线程概念编写的。 因此,没有一个答案就是答案。

在Java中没有相当的东西。


你说的并没有错,这是正确的。问题在于,这并没有真正回答所提出的问题——它只是说其他所有答案都是错误的。你是在说Java中没有相应的东西吗? - Cody Gray
这里的区别对于大多数用户来说都很小。我甚至认为缺乏组播是两者之间更大的区别。就问题的措辞而言,我认为上面的答案都是正确的。所有人都清楚地表明他们正在谈论Java最接近的功能。 - Michael Lloyd Lee mlk
由于引用是原子性的,Java版本不会崩溃,但可能会出现过时的数据。要使其线程安全,您只需要添加关键字“volatile”。 - Michael Lloyd Lee mlk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接