Java中的“SAM类型”是什么?
阅读Java-8规范,我不断看到对“SAM类型”的引用。我无法找到关于这是什么的明确解释。
什么是 SAM 类型,何时可以使用 SAM 类型的示例方案是什么?
阅读Java-8规范,我不断看到对“SAM类型”的引用。我无法找到关于这是什么的明确解释。
什么是 SAM 类型,何时可以使用 SAM 类型的示例方案是什么?
为了总结Jon发布的链接1以防万一它出现故障,“SAM”代表“单个抽象方法”,“SAM类型”指的是,等接口。Lambda 表达式是 Java 8 中的一项新功能,它被视为 SAM 类型,可以自由转换为它们。Runnable
Callable
例如,使用如下界面:
public interface Callable<T> {
public T call();
}
您可以像这样声明一个 using lambda 表达式:Callable
Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"
在此上下文中,Lambda 表达式大多只是语法糖。它们在代码中比匿名类看起来更好,并且对方法命名的限制更少。从链接中举个例子:
class Person {
private final String name;
private final int age;
public static int compareByAge(Person a, Person b) { ... }
public static int compareByName(Person a, Person b) { ... }
}
Person[] people = ...
Arrays.sort(people, Person::compareByAge);
这将创建一个与 不共享相同名称的特定方法,这样您就不必遵循方法的接口命名,并且可以在类中具有多个比较覆盖,然后通过 lambda 表达式动态创建比较器。Comparator
Comparator.compare
更深入...
在更深层次上,Java使用Java 7中添加的字节码指令来实现这些。我之前说过,声明 Lambda 会创建一个匿名类的实例或类似于匿名类,但这并不是严格意义上的。相反,在第一次调用 时,它会使用 LambdaMetafactory.metafactory
方法创建一个 Lambda 函数处理程序,然后在将来调用 Lambda 时使用此缓存的实例。更多信息可以在这个答案中找到。invokedynamic
Callable
Comparable
invokedynamic
这种方法很复杂,甚至包括可以直接从堆栈内存中读取基元值和引用的代码,以传递到您的 Lambda 代码中(例如,绕过需要分配数组来调用 Lambda 的代码),但它允许 Lambda 实现的未来迭代来替换旧的实现,而不必担心字节码兼容性。如果 Oracle 的工程师在较新版本的 JVM 中更改了底层 Lambda 实现,则在较旧的 JVM 上编译的 Lambda 将自动使用较新的实现,而无需开发人员进行任何更改。Object[]
1 链接上的语法已过期。查看 Lambda 表达式 Java Trail 以查看当前语法。