Cod*_*ody 116 java lambda java-8
阅读Java-8规范,我不断看到对"SAM类型"的引用.我无法找到明确解释这是什么.
什么是SAM类型以及什么是何时可以使用的示例场景?
Bri*_*ian 128
总结乔恩发布的链接1的情况下,它不断下降,"SAM"代表"单一抽象方法"和"SAM型"是指接口等Runnable,Callable等Lambda表达式,在Java 8中的新功能,是被认为是SAM类型,可以自由转换为它们.
例如,使用如下界面:
public interface Callable<T> {
public T call();
}
Run Code Online (Sandbox Code Playgroud)
你可以声明一个Callable像这样的lambda表达式:
Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,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);
Run Code Online (Sandbox Code Playgroud)
这会创建一个Comparator使用不同名的特定方法,Comparator.compare这样您就不必遵循方法的接口命名,并且可以在类中进行多个比较覆盖,然后通过动态创建比较器lambda表达式.
走得更远......
在更深层次上,Java使用invokedynamicJava 7中添加的字节码指令实现这些.我之前说过,声明Lambda会创建一个Callable或Comparable类似于匿名类的实例,但这并不严格.相反,第一次invokedynamic调用它时,它使用该LambdaMetafactory.metafactory方法创建一个Lambda函数处理程序,然后在Lambda的将来调用中使用此缓存的实例.更多信息可以在这个答案中找到.
这种方法很复杂,甚至包括可以直接从堆栈内存中读取原始值和引用以传递到Lambda代码的代码(例如,需要分配一个Object[]数组来调用Lambda),但它允许Lambda实现的未来迭代替换旧的实现,而不必担心字节码兼容性.如果Oracle的工程师在较新版本的JVM中更改了基础Lambda实现,则在较旧的JVM上编译的Lambdas将自动使用较新的实现,而无需对开发人员进行任何更改.
1链接上的语法已过期.查看Lambda Expressions Java Trail以查看当前语法.
| 归档时间: |
|
| 查看次数: |
25586 次 |
| 最近记录: |