Java8到Java11新特性和用法介绍

Java8到Java11新特性和用法介绍

Java8新特性概述

Java 8引入了许多令人兴奋的新特性。以下是一些Java 8的主要特性介绍:

  1. Lambda表达式:Lambda表达式是Java 8最显著的特性之一。它们提供了一种简洁的语法来表示匿名函数,可以作为方法参数传递,使得代码更加简洁和易读。

  2. 函数式接口:Java 8引入了函数式接口的概念,它是只有一个抽象方法的接口。函数式接口可以与Lambda表达式一起使用,使得在Java中可以更方便地编写函数式编程风格的代码。

  3. 流(Stream):流是Java 8中新增的一种处理数据集合的抽象。流提供了一种类似于SQL查询的方式来操作集合,可以通过一系列的中间操作(如过滤、映射、排序等)和终端操作(如收集、聚合等)来处理数据。

  4. 方法引用:方法引用提供了一种更简洁的方式来调用已经存在的方法。通过使用双冒号(::)操作符,可以直接引用类的静态方法、实例方法或构造函数。

  5. 默认方法:Java 8允许在接口中定义默认方法。默认方法可以包含方法体实现,使得在接口中添加新方法时不会破坏已有的实现类。

  6. Optional类:Optional类是Java 8为了解决空指针异常而引入的一种方式。它可以包装一个可能为空的值,并提供了一些方法来避免空指针异常的发生。

  7. 新的日期和时间API:Java 8引入了全新的日期和时间API,以替代旧的Date和Calendar类。新的API提供了更好的设计和易用性,同时也解决了旧API中一些常见的问题。

这些是Java 8引入的一些主要特性,它们在提供新功能的同时,也使得Java语言更加现代化和强大。

1.Lambda表达式用法

Lambda表达式是Java 8引入的一项重要特性,它提供了一种简洁的语法来表示匿名函数。Lambda表达式常用于函数式接口的实现,可以替代使用匿名内部类的方式。以下是一些Lambda表达式的用法示例:

  1. 使用Lambda表达式作为函数式接口的实现:
// 定义一个函数式接口
interface MyInterface {
    void doSomething();
}

// 使用Lambda表达式实现接口
MyInterface myInterface = () -> {
    // 在这里编写需要执行的代码块
    System.out.println("Doing something...");
};

// 调用接口的方法
myInterface.doSomething();
  1. 使用Lambda表达式作为函数式接口的参数:
// 定义一个函数式接口
interface MyInterface {
    void doSomething();
}

// 在方法中接受函数式接口作为参数
void performAction(MyInterface action) {
    action.doSomething();
}

// 调用方法,传递Lambda表达式作为参数
performAction(() -> {
    // 在这里编写需要执行的代码块
    System.out.println("Doing something...");
});
  1. 使用Lambda表达式对集合进行操作:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 使用Lambda表达式遍历集合
names.forEach(name -> System.out.println(name));

// 使用Lambda表达式进行过滤
List<String> filteredNames = names.stream()
                                  .filter(name -> name.length() > 4)
                                  .collect(Collectors.toList());

// 使用Lambda表达式进行映射
List<Integer> nameLengths = names.stream()
                                 .map(name -> name.length())
                                 .collect(Collectors.toList());

以上示例展示了Lambda表达式在不同场景下的使用方式。通过Lambda表达式,可以以更简洁的方式编写代码,并提高代码的可读性和易维护性。

2.函数式接口用法

函数式接口是Java 8引入的一个概念,它是只有一个抽象方法的接口。函数式接口通常与Lambda表达式一起使用,可以使代码更具有函数式编程的特点。下面是函数式接口的用法介绍:

  1. 定义函数式接口:
@FunctionalInterface
interface MyFunctionalInterface {
    void doSomething();
}
  • @FunctionalInterface 注解用于标记函数式接口,确保接口只有一个抽象方法。
  • 函数式接口中可以包含默认方法和静态方法,但只能有一个抽象方法。
  1. 使用函数式接口:
  • 使用匿名内部类:
MyFunctionalInterface functionalInterface = new MyFunctionalInterface() {
    @Override
    public void doSomething() {
        // 在这里编写需要执行的代码块
        System.out.println("Doing something...");
    }
};
  • 使用Lambda表达式:
MyFunctionalInterface functionalInterface = () -> {
    // 在这里编写需要执行的代码块
    System.out.println("Doing something...");
};
  1. 函数式接口作为方法参数:

函数式接口的一个重要应用是作为方法参数,可以传递Lambda表达式作为实参。

void performAction(MyFunctionalInterface action) {
    action.doSomething();
}

performAction(() -> {
    // 在这里编写需要执行的代码块
    System.out.println("Doing something...");
});

通过将函数式接口作为方法参数,可以实现灵活的行为传递,将具体的行为作为参数进行传递和执行。

  1. Java内置的函数式接口:

Java 8还提供了一些内置的函数式接口,位于java.util.function包下,用于常见的函数式编程场景。例如:

  • Consumer<T>:消费一个参数,无返回值。
  • Supplier<T>:提供一个值,无参数。
  • Function<T, R>:接受一个参数,返回一个结果。
  • Predicate<T>:接受一个参数,返回一个布尔值。

这些函数式接口可以直接使用,无需自定义,提供了丰富的函数式编程功能。

函数式接口与Lambda表达式的结合可以使代码更加简洁和易读,同时也支持函数式编程风格的代码编写。它们是Java 8中函数式编程特性的基础。

3.流(Stream)用法

流(Stream)是Java 8中引入的一种处理数据集合的抽象。流提供了一种类似于SQL查询的方式来操作集合,可以通过一系列的中间操作和终端操作来处理数据。以下是流的用法介绍:

  1. 创建流:

可以通过集合、数组、I/O通道等方式来创建流。

  • 从集合创建流:
List<String> list = Arrays.asList("Alice", "Bob", "Charlie");
Stream<String> stream = list.stream();
  • 从数组创建流:
String[] array = {"Alice", "Bob", "Charlie"};
Stream<String> stream = Arrays.stream(array);
  • 从文件创建流:
Path path = Paths.get("file.txt");
Stream<String> stream = Files.lines(path);
  1. 中间操作:

中间操作是对流进行转换、过滤和映射等操作的步骤。它们可以按照需要链式调用,形成操作的流水线。

  • 过滤操作:
Stream<String> filteredStream = stream.filter(name -> name.length() > 4);
  • 映射操作:
Stream<Integer> lengthsStream = stream.map(name -> name.length());
  • 排序操作:
Stream<String> sortedStream = stream.sorted();
  • 去重操作:
Stream<String> distinctStream = stream.distinct();
  1. 终端操作:

终端操作是对流进行最终结果计算或收集的操作,它们会触发流的遍历和处理。

  • 遍历输出:
stream.forEach(System.out::println);
  • 收集操作:
List<String> collectedList = stream.collect(Collectors.toList());
  • 匹配操作:
boolean anyMatch = stream.anyMatch(name -> name.startsWith("A"));
boolean allMatch = stream.allMatch(name -> name.length() > 3);
boolean noneMatch = stream.noneMatch(name -> name.endsWith("x"));
  • 聚合操作:
Optional<String> firstElement = stream.findFirst();
Optional<String> anyElement = stream.findAny();
long count = stream.count();

流的中间操作和终端操作可以根据需要组合使用,形成复杂的数据处理流程。通过流,可以简化集合数据的处理,使代码更加简洁和易读。

需要注意的是,流的中间操作是惰性求值的,只有在终端操作触发时才会进行实际的计算和处理。这种延迟求值的机制可以提高效率,并允许对大型数据集进行高效的操作。

4.方法引用用法

方法引用是Java 8中引入的一种语法,用于直接引用已经存在的方法作为Lambda表达式的替代。它提供了一种更简洁的方式来调用已经定义的方法。方法引用可以分为以下几种情况:

  1. 静态方法引用:

可以直接引用已定义的静态方法。

// 静态方法
class MyClass {
    static void myStaticMethod() {
        System.out.println("Hello, World!");
    }
}

// 静态方法引用
Runnable runnable = MyClass::myStaticMethod;
  1. 实例方法引用:

可以直接引用已定义的实例方法。

// 实例方法
class MyClass {
    void myInstanceMethod() {
        System.out.println("Hello, World!");
    }
}

// 实例方法引用
MyClass myObject = new MyClass();
Runnable runnable = myObject::myInstanceMethod;
  1. 对象方法引用:

可以引用已定义的特定对象的实例方法。

// 实例方法
class MyClass {
    void myInstanceMethod() {
        System.out.println("Hello, World!");
    }
}

// 对象方法引用
MyClass myObject = new MyClass();
Consumer<MyClass> consumer = MyClass::myInstanceMethod;
consumer.accept(myObject);
  1. 构造函数引用:

可以引用已定义的构造函数。

// 构造函数
class MyClass {
    MyClass() {
        System.out.println("Creating MyClass object");
    }
}

// 构造函数引用
Supplier<MyClass> supplier = MyClass::new;
MyClass myObject = supplier.get();

在方法引用中,使用::操作符来引用已存在的方法或构造函数。根据引用的方法类型不同,可以选择合适的函数式接口来匹配方法引用。方法引用提供了一种更简洁、更易读的方式来使用已存在的方法,使代码更加简洁和精炼。

5.默认方法用法

默认方法是Java 8引入的一种特性,它允许在接口中定义具有默认实现的方法。默认方法的目的是在不破坏现有实现类的情况下,向接口添加新的方法。以下是默认方法的用法介绍:

  1. 定义默认方法:

默认方法使用default关键字在接口中进行定义,并提供默认的方法实现。

interface MyInterface {
    void myAbstractMethod();

    default void myDefaultMethod() {
        // 默认方法的实现
        System.out.println("Default method");
    }
}
  1. 实现接口:

实现接口时,可以选择是否重写默认方法。如果实现类选择不重写默认方法,将直接继承接口中提供的默认实现。

class MyClass implements MyInterface {
    @Override
    public void myAbstractMethod() {
        // 实现抽象方法的具体逻辑
        System.out.println("Abstract method implementation");
    }
}
  1. 调用默认方法:

默认方法可以通过实现类的实例直接调用,也可以通过接口的引用调用。

MyClass myObject = new MyClass();
myObject.myAbstractMethod(); // 调用抽象方法
myObject.myDefaultMethod(); // 调用默认方法

MyInterface myInterface = new MyClass();
myInterface.myAbstractMethod(); // 调用抽象方法
myInterface.myDefaultMethod(); // 调用默认方法

需要注意的是,如果一个类实现了多个接口,并且这些接口具有相同的默认方法,那么实现类必须重写该方法并提供自己的实现,否则会导致编译错误。在这种情况下,可以使用InterfaceName.super.methodName()的方式调用指定接口的默认方法。

默认方法的引入使得在接口中添加新方法时,不会破坏已有的实现类,同时也避免了创建大量的适配类。默认方法为Java的接口增加了更多的灵活性和可扩展性。

6.Optional类用法

Optional类是Java 8中引入的一个用于处理可能为null的值的容器类。它提供了一种更安全和优雅的方式来处理可能存在空值的情况。以下是Optional类的用法介绍:

  1. 创建Optional对象:

可以使用Optional.of()Optional.ofNullable()Optional.empty()方法来创建Optional对象。

  • Optional.of(value):创建一个非空的Optional对象,如果value为null,则抛出NullPointerException。
Optional<String> optional1 = Optional.of("Hello");
  • Optional.ofNullable(value):创建一个Optional对象,如果value为null,则创建一个空的Optional对象。
String str = null;
Optional<String> optional2 = Optional.ofNullable(str);
  • Optional.empty():创建一个空的Optional对象。
Optional<String> optional3 = Optional.empty();
  1. 判断Optional是否包含值:

可以使用isPresent()方法来判断Optional对象是否包含值。

Optional<String> optional = Optional.of("Hello");
if (optional.isPresent()) {
    System.out.println("Optional contains a value");
} else {
    System.out.println("Optional is empty");
}
  1. 获取Optional中的值:

可以使用get()方法来获取Optional对象中的值。需要注意的是,如果Optional对象为空,则调用get()方法会抛出NoSuchElementException。

Optional<String> optional = Optional.of("Hello");
String value = optional.get();
System.out.println(value);
  1. 使用默认值:

可以使用orElse()方法来获取Optional对象中的值,如果Optional为空,则返回指定的默认值。

Optional<String> optional = Optional.empty();
String value = optional.orElse("Default Value");
System.out.println(value);
  1. 条件判断:

可以使用ifPresent()方法来进行条件判断,如果Optional对象包含值,则执行指定的操作。

Optional<String> optional = Optional.of("Hello");
optional.ifPresent(val -> System.out.println("Value: " + val));
  1. 转换值:

可以使用map()方法对Optional对象中的值进行转换,并返回一个新的Optional对象。

Optional<String> optional = Optional.of("Hello");
Optional<Integer> lengthOptional = optional.map(val -> val.length());
  1. 过滤值:

可以使用filter()方法对Optional对象中的值进行过滤,并返回一个新的Optional对象。

Optional<String> optional = Optional.of("Hello");
Optional<String> filteredOptional = optional.filter(val -> val.length() > 5);

Optional类提供了一种更加优雅和安全的方式来处理可能存在空值的情况。它可以避免在使用null值时产生NullPointerException,并提供了丰富的方法来处理Optional对象中的值。通过合理使用Optional类,可以使代码更加健壮和可靠。

7.新的日期和时间API用法

Java 8引入了新的日期和时间API(java.time包),用于替代旧的Date和Calendar类,提供了更简单、更安全、更易用的日期和时间处理方式。以下是新的日期和时间API的用法介绍:

  1. 创建日期和时间对象:

可以使用LocalDateLocalTimeLocalDateTime类来创建日期和时间对象。

  • LocalDate:表示日期,例如年、月、日。
LocalDate date = LocalDate.now(); // 当前日期
LocalDate specificDate = LocalDate.of(2022, 5, 31); // 指定日期
  • LocalTime:表示时间,例如小时、分钟、秒。
LocalTime time = LocalTime.now(); // 当前时间
LocalTime specificTime = LocalTime.of(12, 30, 45); // 指定时间
  • LocalDateTime:表示日期和时间的组合。
LocalDateTime dateTime = LocalDateTime.now(); // 当前日期和时间
LocalDateTime specificDateTime = LocalDateTime.of(2022, 5, 31, 12, 30, 45); // 指定日期和时间
  1. 格式化和解析日期和时间:

可以使用DateTimeFormatter类来格式化和解析日期和时间。

LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = dateTime.format(formatter); // 格式化为字符串
System.out.println(formattedDateTime);

String dateString = "2022-05-31";
LocalDate parsedDate = LocalDate.parse(dateString, formatter); // 解析字符串为日期对象
System.out.println(parsedDate);
  1. 日期和时间的计算和调整:

可以使用各种方法来进行日期和时间的计算和调整。

  • plusXxx()方法:增加指定的时间量。
LocalDateTime dateTime = LocalDateTime.now();
LocalDateTime newDateTime = dateTime.plusDays(7).plusHours(3);
  • minusXxx()方法:减少指定的时间量。
LocalDate date = LocalDate.now();
LocalDate newDate = date.minusWeeks(1).minusDays(3);
  • withXxx()方法:调整日期或时间的指定部分。
LocalDateTime dateTime = LocalDateTime.now();
LocalDateTime newDateTime = dateTime.withDayOfMonth(15).withHour(10);
  1. 比较和判断日期和时间:

可以使用isBefore()isAfter()isEqual()等方法来比较和判断日期和时间的关系。

LocalDate date1 = LocalDate.of(2022, 5, 31);
LocalDate date2 = LocalDate.of(2023, 1, 1);

boolean isBefore = date1.isBefore(date2);
boolean isAfter = date1.isAfter(date2);
boolean isEqual = date1.isEqual(date2);
  1. 时区和偏移:

可以使用ZoneIdZoneOffset类来表示时区和偏移。

ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZoneOffset zoneOffset = ZoneOffset.ofHours(8);
  1. 日期和时间的转换:

可以使用atZone()方法将日期和时间

Java9新特性概述

Java 9于2017年发布,引入了一些重要的新特性和改进。以下是Java 9的一些主要新特性:

  1. 模块化系统(Java Platform Module System,简称JPMS):
    Java 9引入了模块化系统,允许将代码和依赖项组织为模块,以提供更好的封装和可重用性。模块化系统通过模块描述文件(module-info.java)来定义模块,并引入了模块路径来管理模块之间的依赖关系。

  2. JShell(交互式Java Shell):
    JShell是一个交互式的命令行工具,允许开发者在不编写完整的Java类的情况下进行实时的Java代码交互和测试。它提供了一个类似于REPL(Read-Eval-Print Loop)的环境,可以即时执行代码片段并查看结果。

  3. 改进的Java编译器:
    Java 9引入了一些编译器的改进,如增量编译(Incremental Compilation)和改进的编译器接口(Compiler API),提升了编译速度和效率。

  4. 改进的Java集合库:
    Java 9对集合库进行了一些改进,包括添加了一些新的集合类和接口,如List.of()Set.of()Map.of()等静态工厂方法,用于创建不可变集合。

  5. 改进的Stream API:
    Java 9对Stream API进行了一些改进,包括添加了一些新的方法,如takeWhile()dropWhile(),用于在满足指定条件的情况下截取或丢弃元素。

  6. 多版本兼容的JAR文件:
    Java 9允许在一个JAR文件中包含多个版本的类文件,以便在不同的Java版本中使用适当的类文件。

  7. 改进的安全性:
    Java 9在安全性方面进行了一些改进,包括增强了加密算法、禁用了一些不安全的算法和协议,以及改进了安全管理器等。

除了上述的主要特性之外,Java 9还包含了一些其他改进,如改进的性能、改进的垃圾回收器、新的JavaDoc工具等。总体而言,Java 9引入了一些重要的特性和改进,旨在提升开发者的效率、增强安全性,并改善性能和可维护性。

Java10新特性概述

Java 10于2018年发布,引入了一些新的特性和改进。以下是Java 10的一些主要新特性:

  1. 局部变量类型推断(var关键字):
    Java 10引入了局部变量类型推断,允许在局部变量的声明中使用var关键字来推断变量的类型。这使得代码更加简洁,减少了冗余的类型声明。

  2. 应用程序类数据共享(Application Class-Data Sharing):
    Java 10引入了应用程序类数据共享(AppCDS),允许多个Java虚拟机实例共享已预先编译的类数据。这提供了更快的应用程序启动时间和减少内存占用。

  3. 垃圾回收器接口:
    Java 10引入了一种新的垃圾回收器接口,允许开发者实现自定义的垃圾回收器。这提供了更大的灵活性和可扩展性。

  4. 并行全垃圾收集器(Parallel Full GC):
    Java 10改进了垃圾回收器,引入了并行全垃圾收集器(Parallel Full GC),用于提升全垃圾收集(Full GC)的性能。

  5. 改进的线程局部变量(Thread-Local Handshakes):
    Java 10引入了线程局部变量握手机制(Thread-Local Handshakes),可以在不停止其他线程的情况下与特定线程进行握手,以便更有效地进行协作和优化。

  6. 可选择的GC日志文件:
    Java 10改进了GC日志文件格式,引入了可选择的GC日志文件,提供了更灵活和可读性更强的选项。

  7. 改进的堆内存分配:
    Java 10改进了堆内存分配,引入了一种新的内存分配策略,以提高分配速度和减少内存开销。

  8. 其他改进:
    Java 10还包括一些其他改进,如改进的本地内存(Native Memory Tracking)、改进的时间API等。

请注意,这只是Java 10的一些主要特性和改进。Java平台持续发展,每个版本都带来了新的功能和改进,以提升开发者的体验和应用程序的性能。

Java11新特性概述

Java 11是在2018年发布的Java平台的版本,它引入了一些新的特性和改进。以下是Java 11的一些主要新特性:

  1. 局部变量类型推断的增强:

Java 10中引入了局部变量类型推断(var关键字),Java 11进一步增强了这个特性,允许在Lambda表达式的参数上使用var。

(var x, var y) -> x.process(y)
  1. 字符串新增方法:

String类中新增了一些方便的方法,如isBlank()用于判断字符串是否为空或仅包含空白字符,lines()用于将字符串拆分成行,并返回一个流。

String str = "  Hello, World!  ";
boolean isBlank = str.isBlank();
Stream<String> lines = str.lines();
  1. 新增标准HTTP客户端:

Java 11中引入了一个新的标准HTTP客户端API,替代了过时的HttpURLConnection类。新的HTTP客户端提供了更简洁、易用和灵活的方式来进行HTTP通信。

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("http://example.com"))
        .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String responseBody = response.body();
  1. 升级的垃圾回收器:

Java 11中引入了一个新的垃圾回收器(Epsilon GC),该回收器主要用于性能测试和性能调优,不执行实际的垃圾回收操作。

java -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC MainClass
  1. ZGC垃圾回收器的稳定版发布:

Java 11中,ZGC垃圾回收器由实验性功能转为稳定版,它是一种低延迟的垃圾回收器,适用于大内存应用程序。

java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC MainClass

除了上述的主要特性之外,Java 11还包含了一些其他改进,如支持动态类文件常量、启用HTTP/2、改进的安全性和性能优化等。总体而言,Java 11提供了一些有用的新特性和改进,旨在提升开发人员的效率和应用程序的性能。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值