Java 8 中有委托吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20311779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:59:38  来源:igfitidea点击:

Are there delegates in Java 8?

javadelegateslambdajava-8

提问by R R

Are there delegates in Java 8?

Java 8 中有委托吗?

If not, how do we have lambda expressions in JDK 8 without delegates?

如果没有,我们如何在没有委托的情况下在 JDK 8 中使用 lambda 表达式?

What are method references? Are they the same as delegates?

什么是方法引用?他们和代表一样吗?

采纳答案by gadget

There are no delegates in JDK 8. Under the hood lambdas are instances of functional interfaces (an interface with exactly one abstract method). Depending on where you are passing your lambda the compiler can figure out what interface it is implementing. For example the Collections.sort method accepts a Comparator instance as a second parameter. The Comparator happens to be a functional interface so the compiler will check if the lambda you are passing matches the abstract method in Comparator or not.

JDK 8 中没有委托。在底层,lambda 是函数式接口的实例(一个只有一个抽象方法的接口)。根据您传递 lambda 的位置,编译器可以找出它正在实现的接口。例如 Collections.sort 方法接受一个 Comparator 实例作为第二个参数。Comparator 恰好是一个函数式接口,因此编译器将检查您传递的 lambda 是否与 Comparator 中的抽象方法匹配。

A Method reference is just a simplification. When your lambda is just calling an existing method you can use this new syntax to simplify the construct. The example from the linked tutorial shows it pretty well:

方法引用只是一种简化。当您的 lambda 只是调用现有方法时,您可以使用这种新语法来简化构造。链接教程中的示例很好地显示了它:

instead of:

代替:

Arrays.sort(rosterAsArray,
    (a, b) -> Person.compareByAge(a, b)
);

it's simpler with method reference:

方法参考更简单:

Arrays.sort(rosterAsArray, Person::compareByAge);

Have a look on the lambdafaq.

看看lambdafaq

回答by ToolmakerSteve

Thanks to Pacerier's comment on the question, here is a way to accomplish what a C# (one-function) delegate does, even in Java 7or below.

感谢 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();
    }

}

usage

用法

...
// 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);

yields

产量

result0: 14    <-- f1, so 13 + 1
result1: 14    <-- f1, so 13 + 1
result2: 26    <-- f2, so 2 * 13


NOTE: If you only need a single implementation per-class of a given 'delegate', then the simpler solution is to directly implement the interface on the class. Here is an example. The class already had f3, and now it is extended to implement IA:

注意:如果您只需要一个给定“委托”的每个类的单个实现,那么更简单的解决方案是直接在类上实现接口。这是一个例子。类已经有了f3,现在扩展到实现IA

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

In this case, it is no different than any other interface implementation. The point is that the design conceptreturn a function that matches a specified signaturecan be satisfied, with a bit of extra coding, using Java interfaces. In the second, simpler, case, the interface is placed directly on the class. In the first, more general, case, the interface is placed on an anonymous instance of an anonymous inner class. For clarity and easy access, I isolate those 'delegate creators' in wrapper functions.

在这种情况下,它与任何其他接口实现没有什么不同。关键是可以使用 Java 接口通过一些额外的编码来满足design concept返回与指定签名匹配的函数。在第二种更简单的情况下,接口直接放在类上。在第一种更一般的情况下,接口被放置在匿名内部类的匿名实例上。为了清晰和易于访问,我在包装函数中隔离了那些“委托创建者”。

It is true that the result isn't quite the same as a C# delegate, because one has to do ia.f()rather than ia(). Nevertheless, the design goal has been met.

确实,结果与 C# 委托并不完全相同,因为必须执行ia.f()而不是ia(). 尽管如此,设计目标已经达到。



NOTE: In Java 8, the coding is simplified by use of lambdas. I'm not using Java 8, so I won't include the Java 8 implementation here. (Anyone is welcome to submit an edit that adds that implementation. I suggest showing new bodies below for my wrapF1()and wrapF2()above, as that would make it easy to compare Java 7 and Java 8 versions.)

注意:在Java 8 中,通过使用 lambdas 简化了编码。我没有使用 Java 8,所以我不会在这里包含 Java 8 实现。(欢迎任何人提交添加该实现的编辑。我建议在下面显示我wrapF1()wrapF2()上面的新主体,因为这样可以轻松比较 Java 7 和 Java 8 版本。)