`

转载:Java 7新特性引领Java8

    博客分类:
  • Java
阅读更多

原文:Java 7 Features Which Enable Java 8

It's a truism of the tech industry that developers are never happier than when there's free beer or an opportunity to complain about something on offer.

So despite the efforts of Mark Reinhold and the Java team to involve the community in the roadmap after the Oracle acquisition (the Plan A / Plan B decision), many Java developers feel that Java 7 was "not much of a release".

In this article, I'll try to refute this thesis, by exploring the features in Java 7 which lay the groundwork for the new features in Java 8.

 

 

Java has often been criticised for being overly verbose. One of the most common areas where this complaint is expressed is in assignment. In Java 6, we are forced to write assignment statements like this:

Map<String, String> m = new HashMap<String, String>();

This statement contains a lot of redundant information - we should be able to somehow have the compiler figure out more of this by itself, and not require the programmer to be quite so explicit.

 

In fact, languages like Scala do a large amount of type inference from expressions, and in fact assignment statements can be written as simply as this:

val m = Map("x" -> 24, "y" -> 25, "z" -> 26);

The keyword val indicates that this variable may not be reassigned to (like the keyword final for Java variables). No type information is specified about the variable at all - instead the Scala compiler examines the right-hand side of the assignment and determines the correct type for the variable by looking at which value is being assigned.

In Java 7, some limited type inference capabilities were introduced, and assignment statements can now be written like this:

Map<String, String> m = new HashMap<>();

The key differences between this and the Scala form is that in Scala, values have explicit types, and it is the type of variables that is inferred. In Java 7, the type of variables is explicit, and type information about values is what is inferred.

Some developers have complained that they would have preferred the Scala solution, but it turns out to be less convenient in the context of a major feature for Java 8 - lambda expressions.

In Java 8, we can write a function which adds 2 to an integer like this:

Function<Integer, Integer> fn = x -> x + 2;

The interface Function is new with Java 8 - it resides in the package java.util.function, along with specialized forms for primitive types. However, we've chosen this syntax as it is very similar to the Scala equivalent and allows the developer to see the similarities more easily.

By explicitly specifying the type of fn as a Function which takes one Integer argument and returns another Integer, then the Java compiler is able to infer the type of the parameter x - Integer. This is the same pattern that we saw in Java 7 diamond syntax - we specify the types of variables, and infer the type of values.

Let's look at the corresponding Scala lambda expression:

val fn = (x : Int) => x + 2;

Here, we have to explicitly specify the type of the parameter x, as we don't have the precise type of fn, and so we have nothing to infer from. The Scala form is not hugely difficult to read, but the Java 8 form has a certain cleanliness of syntax which can be directly traced back to the diamond syntax of Java 7.

 

  • Method Handles

Method Handles are simultaneously the most important new feature of Java 7, and the one which is least likely to feature in the day-to-day life of most Java developers.

A method handle is a typed reference to a method for execution. They can be thought of as "typesafe function pointers" (for developers familiar with C/C++) or as "Core Reflection reimagined for the modern Java developer".

Method handles play a huge part in the implementation of lambda expressions. Early prototypes of Java 8 had each lambda expression converted to an anonymous inner class at compile time.

More recent betas are more sophisticated. Let's start by recalling that a lambda expression (at least in Java) comprises a function signature (which in the method handles API will be represented by a MethodType object) and a body, but not necessarily a function name.

This suggests that we could convert the lambda expression into a synthetic method which has the correct signature and which contains the body of the lambda. For example, our example:

Function<Integer, Integer> fn = x -> x + 2;

is turned by the Java 8 compiler into a private method with this bytecode:

 private static java.lang.Integer lambda$0(java.lang.Integer);
   descriptor: (Ljava/lang/Integer;)Ljava/lang/Integer;
   flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
   Code:
    stack=2, locals=1, args_size=1
      0: aload_0
      1: invokevirtual #13 // Method java/lang/Integer.intValue:()I
      4: iconst_2
      5: iadd
      6: invokestatic #8 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      9: areturn

This has the correct signature (takes in an Integer, and returns another one), and semantics. To use this lambda expression, we will take a method handle which refers to it and use it to build an object of the appropriate type, as we'll see in the next feature we discuss.

 

  • invokedynamic

The final feature of Java 7 that opens the door for Java 8 is even more esoteric than method handles. This is the new bytecode invokedynamic - the first new bytecode to be added to the platform since Java 1.0. This feature is almost impossible for Java developers to make use of in version 7, because version 7 javac will not, under any circumstances, emit a classfile which contains it.

Instead, the bytecode was designed for use by developers of non-Java languages, such as JRuby, which require much more dynamic dispatch than Java. To see how invokedynamic works, let's discuss how Java's method calls are compiled into bytecode.

A standard Java method call will be turned into a piece of JVM bytecodes which is often referred to as a call site. This comprises a dispatch opcode (such as invokevirtual, for regular instance method calls) and a constant (an offset into the Constant Pool of the class) which indicates which method is to be called.

The different dispatch opcodes have different rules that govern how method lookup is done, but until Java 7 the constant was always a straightforward indication of which method was to be called.

invokedynamic is different. Instead of providing a constant which directly indicates which method is to be called, invokedynamic instead provides an indirection mechanism that allows user code to decide which method to call at runtime.

When an invokedynamic site is first encountered, it does not have a known target yet. Instead, a method handle (called a bootstrap method) is invoked. This bootstrap method returns a CallSite object, which contains another method handle, which is the actual target of the invokedynamic call.

1) invokedynamic site encountered in the execution stream (initially unlinked) 2) Call bootstrap method and return a CallSite object 3) CallSite object contains a method handle (the target) 4) Invoke the target method handle

The bootstrap method is the way in which user code chooses which method needs to be called. For lambda expressions, the platform uses a library-supplied bootstrap method called a lambda meta-factory.

This has static arguments which contain a method handle to the synthesized method (see last section), and the correct signature for the lambda.

The meta-factory returns a CallSite that contains a method handle which will in turn return an instance of the correct type that the lambda expression has been converted to. So a statement like:

Function<Integer, Integer> fn = x -> x + 2;

is converted to an invokedynamic call like this:

Code:
  stack=4, locals=2, args_size=1
     0: invokedynamic #2, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
     5: astore_1

The invokedynamic bootstrap method is the static method LambdaMetafactory.metafactory(), which returns a CallSite object which is linked to a target method handle, which will return an o bject which implements the Function interface.

When the invokedynamic instruction is complete, an object which implements Function and which has the lambda expression as the contents of its apply() method is sat on top of the stack, and the rest of the code can proceed normally.

  • Conclusion

Getting lambda expressions into the Java platform was always going to be a challenging endeavour, but by ensuring that the proper groundwork was in place, Java 7 eased that effort considerably. Plan B not only provided developers with the early release of Java 7 but also allowed core technologies to be made fully road-tested before their use in Java 8 and especially in lambda expressions.

About the Author

Ben Evans is the CEO of jClarity, a startup which delivers performance tools to help development & ops teams. He is an organizer for the LJC (London JUG) and a member of the JCP Executive Committee, helping define standards for the Java ecosystem. He is a Java Champion; JavaOne Rockstar; co-author of “The Well-Grounded Java Developer” and a regular public speaker on the Java platform, performance, concurrency, and related topics.

分享到:
评论

相关推荐

    java错误处理:java.lang.OutOfMemoryError: Java heap space

    ### Java 错误处理:java.lang.OutOfMemoryError: Java heap space 在Java应用程序开发过程中,经常遇到的一个问题就是内存溢出错误,特别是在处理大量数据或长时间运行的应用时。其中,“java.lang....

    黑马程序员_java8新特性详解笔记和源码

    本文将深入探讨Java 8的三大关键新特性:接口的默认方法实现、Lambda表达式以及一系列相关的变化。 一、接口的默认方法实现 在Java 8之前,接口只能定义抽象方法,而不能包含具体实现。Java 8引入了默认方法...

    编程选择题40道:Java 9及以后:模块系统与新特性.Tex.docx

    编程选择题40道:Java 9及以后:模块系统与新特性.Tex.docx

    java7 32位版

    Java 7,又称为Java SE 7 (Java Standard Edition 7),是Java的重要里程碑,它在2011年发布,带来了许多新特性和性能优化。以下是一些关键的Java 7特性: 1. **多语言支持**:Java 7引入了新的`try-with-resources`...

    尚硅谷Java视频Java8新特性视频教程

    尚硅谷Java视频Java8新特性视频教程,本Java视频涵盖了 Java8 的所有新特性:Lambda表达式、强大的 Stream API、全新时间日期 API、ConcurrentHashMap、MetaSpace。Java8 的新特性使 Java 的运行速度更快、代码更少...

    Java8 jdk安装包

    7. ** Nashorn JavaScript引擎**:Java8集成了Nashorn JavaScript引擎,允许Java代码与JavaScript交互,提高了平台间的互操作性。 8. **Optional类**:为了解决null安全问题,Java8引入了`Optional`类。它是一个...

    Java 8 API 中版chm手册

    7. ** Nashorn JavaScript引擎**:Java 8包含了Nashorn JavaScript引擎,允许Java代码直接执行JavaScript,提供了Java与JavaScript之间的互操作性。 8. **类型接口**:在泛型声明中可以使用类型接口,如`List...

    Java2核心技术卷2:高级特性 第7版 中文高清 PDF JAVA经典巨著 经久不衰 part02

    Java2核心技术卷2:高级特性 第7版 中文高清 PDF JAVA经典巨著 经久不衰 part02

    读书笔记:java 虚拟机,深入理解Java虚拟机 JVM高级特性与最佳实践 .zip

    读书笔记:java 虚拟机,深入理解Java虚拟机 JVM高级特性与最佳实践

    java7 32+64位安装包下载

    6. **兼容性**:Java 7可以运行大部分基于Java的软件,但某些较新的特性可能需要Java 8或更高版本才能使用。开发者在部署应用时,应考虑目标用户的Java环境,确保兼容性。 7. **卸载与更新**:如果需要卸载或更新...

    java源码包---java 源码 大量 实例

    内容索引:JAVA源码,综合应用,J2me游戏,PNG,图形处理  这是个J2ME控制台程序,它能剔除PNG文件中的非关键数据段,减少文件大小从而达到压缩图片的目的。而图片的质量并不会受到损失。使用时候只需在控制台窗口执行...

    Java8 64位免安装版

    JDK8是Oracle公司发布的Java平台标准版(Java SE)的一个重要版本,引入了许多新特性,对开发者的工作效率和代码质量产生了显著提升。 1. **Lambda表达式**:Java 8最重要的特性之一就是引入了Lambda表达式,这是一...

    最新Java JDK 8免安装版(Linux 64位)

    Java JDK 8是Java平台标准版(Java SE)的一个重要里程碑,它引入了许多新特性,对开发者的工作效率和代码质量产生了显著提升。 1. **Lambda表达式**:Java 8引入了函数式编程的概念,Lambda表达式是最显著的特征之...

    JAVA8API-官方文档下载-中文版

    这份中文版的官方文档使得国内开发者能够更加方便地理解和使用Java 8的新特性,提升开发效率。 **核心语言特性** 1. **lambda表达式**: Java 8引入了函数式编程的概念,通过lambda表达式可以简洁地表示匿名函数,...

    java 8 安装包

    7. ** Nashorn JavaScript引擎**:Java 8内置了Nashorn JavaScript引擎,可以直接在Java程序中执行JavaScript代码,实现Java与JavaScript的交互。 8. **并行GC的改进**:包括G1垃圾收集器的增强,以及CMS...

    JDK18-java-se-language-updates.pdf

    1. 提高开发效率:Java 语言更新的新特性和改进使得开发者可以更加快速和高效地开发 Java 应用程序。 2. 提高应用性能:Java 语言更新的新特性和改进使得 Java 应用程序的性能得到了显著的改善。 3. 提高应用安全:...

    Java JDK 7学习笔记 PDF

    Java JDK 7是Java开发工具包的一个重要版本,它的全称是Java Development Kit,是用于构建和运行Java应用程序的关键组件。...通过这份PDF学习笔记,读者将能深入理解JDK 7的新特性,并能将其应用到实际项目中。

    JAVA经典100个小案例

    9. **函数式编程**:Java 8引入了Lambda表达式和Stream API,案例会展示如何利用这些新特性进行函数式编程。 10. **多线程**:Java支持并发编程,案例会讲解如何创建和管理线程,以及同步和互斥的概念。 通过这些...

    java8帮助文档中文版API

    9. **改进的并发**:Java 8对`ForkJoinPool`和`RecursiveTask`进行了优化,提升了并行计算性能,同时`ConcurrentHashMap`也有了改进,提供了新的`computeIfAbsent()`, `merge()`, `forEach()`等方法。 10. **接口的...

    JAVAX86 JAVA环境最新版

    每个新版本通常会带来性能提升、新特性和安全修复,所以保持Java环境的更新对于确保代码的安全性和效率至关重要。 5. **安装与配置**: 安装"JAVAX86.exe"时,用户通常会通过图形界面引导进行,选择安装路径、设置...

Global site tag (gtag.js) - Google Analytics