Java 中的“SAM 类型"是什么? [英] What is a 'SAM type' in Java?

查看:45
本文介绍了Java 中的“SAM 类型"是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读 Java-8 规范的过程中,我不断看到对SAM 类型"的引用.我一直没能找到关于这是什么的清楚解释.

Reading up on the Java-8 spec, I keep seeing references to 'SAM types'. I haven't been able to find a clear explanation of what this is.

什么是 SAM 类型以及何时可能使用的示例场景是什么?

What is a SAM type and what is an example scenario of when one might be used?

推荐答案

总结 Jon 发布的链接1 以防它出现故障,SAM"代表单一抽象方法",SAM-type"指的是像 RunnableCallable 等.Lambda 表达式是 Java 8 中的一个新特性,被认为是一种 SAM 类型,可以自由转换为它们.

To summarize the link Jon posted1 in case it ever goes down, "SAM" stands for "single abstract method", and "SAM-type" refers to interfaces like Runnable, Callable, etc. Lambda expressions, a new feature in Java 8, are considered a SAM type and can be freely converted to them.

以这样的界面为例:

public interface Callable<T> {
    public T call();
}

您可以使用如下 lambda 表达式声明 Callable:

You can declare a Callable using lambda expressions like this:

Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"

在这种情况下,Lambda 表达式大多只是语法糖.它们在代码中看起来比匿名类更好,并且对方法命名的限制更少.从链接中获取此示例:

Lambda expressions in this context are mostly just syntactic sugar. They look better in code than anonymous classes and are less restrictive on method naming. Take this example from the link:

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

这会使用与 Comparator.compare 不同名称的特定方法创建一个 Comparator,这样您就不必遵循接口命名方法,您可以在一个类中有多个比较覆盖,然后通过 lambda 表达式动态创建比较器.

This creates a Comparator using a specific method that doesn't share the same name as Comparator.compare, that way you don't have to follow the interface naming of methods and you can have multiple comparison overrides in a class, then create the comparators on the fly via the lambda expressions.

深入...

在更深的层次上,Java 使用 Java 7 中添加的 invokedynamic 字节码指令来实现这些.我之前说过,声明一个 Lambda 会创建一个 Callable 的实例>Comparable 类似于匿名类,但这不是严格正确的.相反,第一次调用 invokedynamic 时,它会使用 LambdaMetafactory.metafactory 方法,然后在以后的 Lambda 调用中使用这个缓存的实例.更多信息可以在这个答案中找到.

On a deeper level, Java implements these using the invokedynamic bytecode instruction added in Java 7. I said earlier that declaring a Lambda creates an instance of Callable or Comparable similar to an anonymous class, but that's not strictly true. Instead, the first time the invokedynamic is called, it creates a Lambda function handler using the LambdaMetafactory.metafactory method, then uses this cached instance in future invocations of the Lambda. More info can be found in this answer.

这种方法很复杂,甚至包括可以直接从堆栈内存读取原始值和引用以传递到您的 Lambda 代码的代码(例如,避免需要分配一个 Object[] 数组来调用您的 Lambda),但它允许 Lambda 实现的未来迭代替换旧的实现,而不必担心字节码兼容性.如果 Oracle 的工程师在较新版本的 JVM 中更改底层 Lambda 实现,则在较旧 JVM 上编译的 Lambda 将自动使用较新的实现,而无需开发人员进行任何更改.

This approach is complex and even includes code that can read primitive values and references directly from stack memory to pass into your Lambda code (e.g. to get around needing to allocate an Object[] array to invoke your Lambda), but it allows future iterations of the Lambda implementation to replace old implementations without having to worry about bytecode compatibility. If the engineers at Oracle change the underlying Lambda implementation in a newer version of the JVM, Lambdas compiled on an older JVM will automatically use the newer implementation without any changes on the developer's part.

1 链接上的语法已过时.查看Lambda Expressions Java Trail 以查看当前语法.

1 The syntax on the link is out of date. Take a look at the Lambda Expressions Java Trail to see the current syntax.

这篇关于Java 中的“SAM 类型"是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆