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

查看:222
本文介绍了什么是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指的是 Runnable Callable 等接口.Ladda表达式是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表达式:

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 它与 Comparator.compare 的名称不同,这样您就不必遵循方法的接口命名,并且可以在类中进行多次比较覆盖,然后通过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会创建一个<$ c的实例$ c> 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上编译的Lambdas将自动使用较新的实现,而不会对开发人员进行任何更改。

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天全站免登陆