JDK 8 中没有委托。在引擎盖下,lambdas是功能接口的实例(一个只有一个抽象方法的接口)。根据您传递 lambda 的位置,编译器可以确定它正在实现的接口。例如,Collections.sort 方法接受比较器实例作为第二个参数。比较器恰好是一个函数接口,因此编译器将检查您传递的 lambda 是否与比较器中的抽象方法匹配。
方法引用只是一种简化。当您的 lambda 只是调用现有方法时,您可以使用此新语法来简化构造。链接教程中的示例很好地显示了这一点:
而不是:
Arrays.sort(rosterAsArray,
    (a, b) -> Person.compareByAge(a, b)
);
使用方法引用更简单:
Arrays.sort(rosterAsArray, Person::compareByAge);
看看lambdafaq。
感谢 Pacerier 对这个问题的评论,这里有一种方法可以完成 C#(单函数)委托的功能,即使在 Java 7 或更低版本中也是如此。
// This defines the 'delegate'.
public interface IA {
    int f(int a);
}
public class MyClass {
    // f1 and f2 have the same signature as 'IA.f'.
    private int f1(int a) {
        return a + 1;
    }
    private int f2(int a) {
        return 2 * a;
    }
    // These wrappers are one way to return a 'delegate'.
    // Each wrapper creates one instance of an anonymous class.
    // Notice that we did not have to declare MyClass as implementing IA,
    // and that we can wrap different methods of MyClass into 'IA's.
    // Contrast this with 'MyClass implements IA', which would require
    // a method 'f' in 'MyClass', and would not provide a way to
    // delegate to different methods of 'MyClass'.
    public IA wrapF1() {
        return (new IA(){
            public int f(int a) {
                return f1(a);
            }
        });
    }
    public IA wrapF2() {
        return (new IA(){
            public int f(int a) {
                return f2(a);
            }
        });
    }
    // returns a 'delegate', either to 'f1' or 'f2'.
    public IA callMe(boolean useF2) {
        if (!useF2)
            return wrapF1();
        else
            return wrapF2();
    }
}
用法
...
// Create and use three 'delegates'.
// Technically, these are not quite the same as C# delegates,
// because we have to invoke a method on each.
// That is, we must do 'ia0.f(..)' instead of 'ia0(..)'.
// Nevertheless, it satisfies the design requirement.
MyClass c = new MyClass();
IA ia0 = c.wrapF1();
IA ia1 = c.callMe(false);
IA ia2 = c.callMe(true);
int result0 = ia0.f(13);
int result1 = ia1.f(13);
int result2 = ia2.f(13);
收益 率
result0: 14    <-- f1, so 13 + 1
result1: 14    <-- f1, so 13 + 1
result2: 26    <-- f2, so 2 * 13
注意:如果给定的“委托”的每个类只需要一个实现,那么更简单的解决方案是直接在类上实现接口。下面是一个示例。该类已经有 ,现在它被扩展为实现:f3IA
public class MyClass2
        implements IA {
    private int baseValue;
    private int anotherValue;
    public MyClass2(int baseValue, int anotherValue) {
        this.baseValue = baseValue;
        this.anotherValue = anotherValue;
    }
    public int f3(int v1, int v2) {
        return 2 * v1 + v2;
    }
    public int f(int a) {
        return f3(baseValue + a, anotherValue);
    }
}
IA ia3 = new MyClass2(10, 3);
int result3 = ia3.f(13);   // = f3(10 + 13) = 2 * 23 + 3 = 49
在这种情况下,它与任何其他接口实现没有什么不同。关键是,使用 Java 接口,只需进行一些额外的编码,就可以满足与指定签名匹配的函数的返回。在第二种更简单的情况下,接口直接放置在类上。在第一种更一般的情况下,接口放置在匿名内部类的匿名实例上。为了清晰和易于访问,我将这些“委托创建者”隔离在包装器函数中。design concept
确实,结果与 C# 委托并不完全相同,因为必须执行 而不是 。尽管如此,设计目标还是已经实现。ia.f()ia()
注意:在 Java 8 中,通过使用 lambdas 简化了编码。我没有使用Java 8,所以我不会在这里包括Java 8实现。(欢迎任何人提交添加该实现的编辑。我建议在下面为我和上面显示新的主体,因为这样可以很容易地比较Java 7和Java 8版本。wrapF1()wrapF2()
- 
					    	使用 lambda 妨碍类型变量的推理 我有以下成功编译的代码: 如果我将供应商的声明更改为 ,则两个变体都编译成功。 我使用Java 8编译器编译代码。 为什么带有lambda的代码无法编译,尽管它等同于非lambda版本?这是Java的已
				    		 - 
					    	
					    				    		
				    		 - 
					    	过滤功能不懒惰 我正在制作我自己的Java流库版本,以此为乐。这是我的班级签名: 我该如何解决这个问题,有没有办法通过懒惰的减少来实现懒惰的过滤器? 致谢:这个练习和上述函数的实现受到Chiusano和B
				    		 - 
					    	确保函数参数可序列化的最佳方法是什么? 我正在编写一个可序列化的类,它接受几个参数,包括:存储在成员变量中,因此需要可序列化。如果 Java lambdas 内部以 bolt 形式运行的类,该类被序列化以传输到 remove 群集以执行。在集群上
				    		 - 
					    	使用 Eclipse 编译器编译时,LocalVariableTypeTable 中奇怪的 “!*” 条目 让我们使用 Eclipse Mars.2 捆绑包中的 ECJ 编译器编译以下代码: 我很惊讶地看到这个条目。JVM规范 定义了字段签名的语法,如果我理解正确,它不包括与 .