jdk8系列一、jdk新特性

一、简介

毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。

在本文中我们将学习这些新特性,并用实际的例子说明在什么场景下适合使用。

包含Java开发者经常面对的几类问题:

  • 语言
  • 编译器
  • 工具
  • 运行时(JVM)

二、Lambda表达式和函数式接口

  Lambda表达式(也称为闭包)是Java 8中最大和最令人期待的语言改变。它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理:函数式开发者非常熟悉这些概念。

  很多JVM平台上的语言(Groovy、Scala等)从诞生之日就支持Lambda表达式,但是Java开发者没有选择,只能使用匿名内部类代替Lambda表达式。

  Lambda的设计耗费了很多时间和很大的社区力量,最终找到一种折中的实现方案,可以实现简洁而紧凑的语言结构。

1、Lamda表达式语法

 最简单的Lambda表达式可由逗号分隔的参数列表、->符号和语句块组成,例如:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

在上面这个代码中的参数e的类型是由编译器推理得出的,你也可以显式指定该参数的类型,例如:

Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );

2、Lamda表达式语句块

如果Lambda表达式需要更复杂的语句块,则可以使用花括号将该语句块括起来,类似于Java中的函数体,例如:

    public static void main(String[] args) {
        String separator = ",";
        Arrays.asList("a","b","c").forEach((String e) -> {
            System.out.print(e + separator);
            System.out.println(e);
        });
    }

Lambda表达式可以引用类成员和局部变量(会将这些变量隐式得转换成final的),例如下列两个代码块的效果完全相同:

String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
    ( String e ) -> System.out.print( e + separator ) );

final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
    ( String e ) -> System.out.print( e + separator ) );

3、处理返回值

Lambda表达式有返回值,返回值的类型也由编译器推理得出。如果Lambda表达式中的语句块只有一行,则可以不用使用return语句,下列两个代码片段效果相同:

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
    int result = e1.compareTo( e2 );
    return result;
} );

4、函数接口

  Lambda的设计者们为了让现有的功能与Lambda表达式良好兼容,考虑了很多方法,于是产生了函数接口这个概念。函数接口指的是只有一个函数的接口,这样的接口可以隐式转换为Lambda表达式。java.lang.Runnablejava.util.concurrent.Callable是函数式接口的最佳例子。在实践中,函数式接口非常脆弱:只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface(Java 库中的所有相关接口都已经带有这个注解了),举个简单的函数式接口的定义:

@FunctionalInterface
public interface Functional {
    void method();
}

不过有一点需要注意,默认方法和静态方法不会破坏函数式接口的定义,因此如下的代码是合法的。

@FunctionalInterface
public interface FunctionalDefaultMethods {
    void method();

    default void defaultMethod() {
    }
}

更多可以参考官方文档

三、接口的默认方法和静态方法

1、允许接口有默认实现

  Java 8使用两个新概念扩展了接口的含义:默认方法和静态方法。默认方法使得接口有点类似traits,不过要实现的目标不一样。默认方法使得开发者可以在 不破坏二进制兼容性的前提下,往现存接口中添加新的方法,即不强制那些实现了该接口的类也同时实现这个新加的方法。

  默认方法和抽象方法之间的区别在于抽象方法需要实现,而默认方法不需要。接口提供的默认方法会被接口的实现类继承或者覆写,例子代码如下:

private interface Defaulable {
    // Interfaces now allow default methods, the implementer may or
    // may not implement (override) them.
    default String notRequired() {
        return "Default implementation";
    }
}

private static class DefaultableImpl implements Defaulable {
}

private static class OverridableImpl implements Defaulable {
    @Override
    public String notRequired() {
        return "Overridden implementation";
    }
}

2、接口静态方法

Defaulable接口使用关键字default定义了一个默认方法notRequired()DefaultableImpl类实现了这个接口,同时默认继承了这个接口中的默认方法;OverridableImpl类也实现了这个接口,但覆写了该接口的默认方法,并提供了一个不同的实现。

Java 8带来的另一个有趣的特性是在接口中可以定义静态方法,例子代码如下:

private interface DefaulableFactory {
    // Interfaces now allow static methods
    static Defaulable create( Supplier< Defaulable > supplier ) {
        return supplier.get();
    }
}

下面的代码片段整合了默认方法和静态方法的使用场景:

public static void main( String[] args ) {
    Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );
    System.out.println( defaulable.notRequired() );

    defaulable = DefaulableFactory.create( OverridableImpl::new );
    System.out.println( defaulable.notRequired() );
}

这段代码的输出结果如下:

Default implementation
Overridden implementation

  由于JVM上的默认方法的实现在字节码层面提供了支持,因此效率非常高。默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()parallelStream()forEach()removeIf()等等。

  尽管默认方法有这么多好处,但在实际开发中应该谨慎使用:在复杂的继承体系中,默认方法可能引起歧义和编译错误。如果你想了解更多细节,可以参考官方文档

原文地址:https://www.cnblogs.com/wangzhuxing/p/10204436.html

时间: 2024-10-11 07:31:59

jdk8系列一、jdk新特性的相关文章

重踏学习Java路上_Day27(反射,模式设计,jdk新特性)

1:反射(理解) (1)类的加载及类加载器 (2)反射: 通过字节码文件对象,去使用成员变量,构造方法,成员方法 (3)反射的使用 A:通过反射获取构造方法并使用 B:通过反射获取成员变量并使用 C:通过反射获取成员方法并使用 (4)反射案例 A:通过反射运行配置文件的内容 B:通过反射越过泛型检查 C:通过反射给任意的一个对象的任意的属性赋值为指定的值 (5)动态代理 2:设计模式 (1)装饰设计模式 BufferedReader br = new BufferedReader(new Inp

jdk新特性——可变参数

public class array2{ public static void main(String[] args) { sayHello("beijing","xian"); } private static void sayHello(String ... args) { for (int i = 0; i < args.length; i++) System.out.println("hello," + args[i]+"

Exchange Server2013系列一:新特性

说来惭愧,Exchange Server 2013已经发布近一年半的时间了,但一直没能抽出时间折腾一把.近来正好有项目要用到,准备把Exchange Server 2013大体梳理一下,写几篇文章,以便于掌握Exchange Server2013中的相关知识点. 相对于前期版本来说Exchange 2013引入了一些新的技术和功能,不论是对Outlook 2013以及OWA的用户界面支持,还是整个Exchange体系架构:从管理工具到邮件的安全合规:从全新部署到Exchange升级,都有不少亮点

JavaEE基础(二十七)/反射、JDK新特性

1.反射(类的加载概述和加载时机) A:类的加载概述 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 加载  就是指将class文件读入内存,并为之创建一个Class对象.任何类被使用时系统都会建立一个Class对象. 连接 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数据中的符号引用替换为直接引用 初始化 就是我们以前讲过的初始化步骤 B:加载时机 创建类

黑马程序员----java基础--JDK新特性和集合其他类

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.JDK1.5新特性 JDK升级的三大原因: (1).提高代码的复用性 (2).提高代码的安全性 (3).简化书写 1.泛型机制 JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. (1).泛型概念 泛型是根据数组的思想设计出来的,因为数组一旦建立成功就已经明确了数据类型,所以可根据数组思想给集合指定类型. 如:数组:int[] arr=new int[4]; 而集合的泛

Java系列 – 用Java8新特性进行Java开发太爽了(续)

本人博客文章网址:https://www.peretang.com/using-java8s-new-features-to-coding-is-awesome-2/ 前言 上周, 我们谈论了关于Java8的新特性有那些, 什么是函数式编程, 什么是Lambda表达式, 这周让我们继续谈论这些新特性. 本周, 我们会聊一下什么是Stream API, 以及什么是Optional. Stream API你让我想重写我以前的所有代码 "Stream API你让我想重写我以前的所有代码",

iOS 11系列 - Xcode 9新特性

Xcode 9最近刚刚发布,带来了一系列不错的新特性,可以更好的帮助到开发者完成开发工作. Xcode Runtime Tool Xcode 9中有许多Runtime Tool可以帮助开发者找到代码错误,包括如下: Main Thread Checker  -  Xcode 9新引入 Address Sanitizer Thread Sanitizer Undefined Behavior Sanitizer Using Runtime Tools Effectively Main Thread

jdk新特性

jdk从1.7开始采用下划线分隔符来分隔比较长的数. 如:int  a=0b0000_0000_0000_0000_0000_0000_0000_0011; //0b开头代表二进制 ,也就是3在真实内存中的存储(除分隔符) int  b=12_4567_9010; //采用下划线分隔符让人一目了然

javaEE学习笔记【02】JDK新特性

泛型的使用 原则"使用泛型的时候左右两边要一致!" 1 2 3 List  list = new ArrayList<String>();     //add提示的是Object List<String>  list = new ArrayList ();    //add提示的是String List<String>  list = new ArrayList<String>();  //add提示的是String 以上的语法全对,但是