java 8的 新特性

it2022-05-05  101

一. Lambda 表达式

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。

方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

以下是lambda表达式的重要特征:

可选类型声明: 不需要声明参数类型,编译器可以统一识别参数值。

可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选的大括号: 如果主体包含了一个语句,就不需要使用大括号。

可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。 Lambda表达式实例

Java8Tester tester = new Java8Tester(); // 类型声明 MathOperation addition = (int a, int b) -> a + b; // 不用类型声明 MathOperation subtraction = (a, b) -> a - b; // 大括号中的返回语句 MathOperation multiplication = (int a, int b) -> { return a * b; }; // 没有大括号及返回语句 MathOperation division = (int a, int b) -> a / b; System.out.println("10 + 5 = " + tester.operate(10, 5, addition)); System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + tester.operate(10, 5, division)); // 不用括号 GreetingService greetService1 = message -> System.out.println("Hello " + message); // 用括号 GreetingService greetService2 = (message) -> System.out.println("Hello " + message); greetService1.sayMessage("Runoob"); greetService2.sayMessage("Google"); } interface MathOperation { int operation(int a, int b); } interface GreetingService { void sayMessage(String message); } private int operate(int a, int b, MathOperation mathOperation){ return mathOperation.operation(a, b); }

使用 Lambda 表达式需要注意以下两点:

Lambda表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。

Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力

变量作用域 lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

final static String salutation = "Hello! "; public static void main(String args[]){ GreetingService greetService1 = message -> System.out.println(salutation + message); greetService1.sayMessage("Runoob"); } interface GreetingService { void sayMessage(String message); } }

我们也可以直接在 lambda 表达式中访问外层的局部变量:

public class Java8Tester { public static void main(String args[]) { final int num = 1; Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2); // 输出结果为 3 } public interface Converter<T1, T2> { void convert(int i); } }

lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

在 Lambda 表达式当中不允许声明一个与局部变量同名的 参数或者 局部变量。

二. 默认方法

− 默认方法就是一个在接口里面有了一个实现的方法。

三. 新工具

− 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

四.Stream API

−新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

五.Date Time API

− 加强对日期与时间的处理。

非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。

设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。

时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和 java.util.TimeZone类,但他们同样存在上述所有的问题。

Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:

Local(本地) − 简化了日期时间的处理,没有时区的问题。

Zoned(时区) − 通过制定的时区处理日期时间。

Date类

这里的Date是位于java.util包下的类,而不是java.sql包下的date类,Date对象即包含日期也包含时间,从JDK1.0就开始存在了,历史相当悠久,因此,它的大部分构造器和方法已经过时了,不在推荐使用。

Date提供了6个构造器,其中4个已经Deprecated(不推荐使用了,如果继续使用,编 译器会提出警告信息,并导致程序性能和安全性方面的问题),剩下2个构造器如下: Date():生成一个代表当前日期的Date对象。该构造器在底层调用 System.currentTimeMillis()获得long长整数作为日期参数。

Date(long date):根据指定的long型整数生成一个Date对象。该构造器的参数表示创建的Date对象和GMT1970年1月1日00:00:00之间的时间差,以毫秒为单位。

本地化日期时间 API -LocalDate/LocalTime 和 LocalDateTime 类可以在处理时区不是必须的情况。

// 获取当前的日期时间 LocalDateTime currentTime = LocalDateTime.now(); System.out.println("当前时间: " + currentTime); LocalDate date1 = currentTime.toLocalDate(); System.out.println("date1: " + date1); Month month = currentTime.getMonth(); int day = currentTime.getDayOfMonth(); int seconds = currentTime.getSecond(); System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds); LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012); System.out.println("date2: " + date2); // 12 december 2014 LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12); System.out.println("date3: " + date3); // 22 小时 15 分钟 LocalTime date4 = LocalTime.of(22, 15); System.out.println("date4: " + date4); // 解析字符串 LocalTime date5 = LocalTime.parse("20:15:30"); System.out.println("date5: " + date5);

使用时区的日期时间API

Java8Tester java8Tester = new Java8Tester(); Integer value1 = null; Integer value2 = new Integer(10); // Optional.ofNullable - 允许传递为 null 参数 Optional<Integer> a = Optional.ofNullable(value1); // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException Optional<Integer> b = Optional.of(value2); System.out.println(java8Tester.sum(a,b)); } public Integer sum(Optional<Integer> a, Optional<Integer> b){ // Optional.isPresent - 判断值是否存在 System.out.println("第一个参数值存在: " + a.isPresent()); System.out.println("第二个参数值存在: " + b.isPresent()); // Optional.orElse - 如果值存在,返回它,否则返回默认值 Integer value1 = a.orElse(new Integer(0)); //Optional.get - 获取值,值需要存在 Integer value2 = b.get(); return value1 + value2; }

使用时区的日期时间API

// 获取当前时间日期 ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]"); System.out.println("date1: " + date1); ZoneId id = ZoneId.of("Europe/Paris"); System.out.println("ZoneId: " + id); ZoneId currentZone = ZoneId.systemDefault(); System.out.println("当期时区: " + currentZone); }

六.Optional 类

− Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。Optional 类的引入很好的解决空指针异常。

七.Nashorn, JavaScript 引擎

− Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

个人笔记 应用于 菜鸟教程


最新回复(0)