一分钟掌握java9新特性

try-with-resources语句

/**  
 * 在处理必须关闭的资源时,使用try-with-resources语句替代try-finally语句。 生成的代码更简洁,更清晰,并且生成的异常更有用  
 * java9 之前写法  
 */  
public static String readFile1(String fileName){  
    try (Reader inputString = new StringReader(fileName);  
         BufferedReader br = new BufferedReader(inputString)) {  
        return br.readLine();  
    } catch (IOException e) {  
        throw new RuntimeException(e);  
    }  
}  
  
/**  
 * 在处理必须关闭的资源时,使用try-with-resources语句替代try-finally语句。 生成的代码更简洁,更清晰,并且生成的异常更有用  
 * java9之后写法  
 */  
public static String readFile2(String fileName){  
    Reader inputString = new StringReader(fileName);  
    BufferedReader br = new BufferedReader(inputString);  
    try (br) {  
        return br.readLine();  
    } catch (IOException e) {  
        throw new RuntimeException(e);  
    }  
}

改进的集合工厂方法

Java 9 提供了一些新的静态工厂方法 List.of(), Set.of(), 和 Map.of() 来创建不可变集合。

示例代码

public static void main(String[] args) {  
    List<Integer> list = List.of(1, 2, 3);  
    Set<Integer> set = Set.of(1, 2, 3);  
    Map<String, Integer> map = Map.of("one", 1, "two", 2, "three", 3);  
    System.out.println(list);  
    System.out.println(set);  
    System.out.println(map);  
}

控制台输出

[1, 2, 3]
[1, 2, 3] 
{two=2, three=3, one=1}

增强流(Stream)API

takeWhile 方法

takeWhile 方法允许你在满足给定的谓词条件下获取流中的元素,直到第一个不满足条件的元素出现为止。

示例代码

public static void main(String[] args) {  
    List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
  
    List<Integer> takeWhileList = numbers.stream()  
            .takeWhile(n -> n < 5)  
            .collect(Collectors.toList());  
  
    System.out.println("Take while: " + takeWhileList);  
}

控制台输出

Take while: [1, 2, 3, 4]

dropWhile 方法

dropWhile 方法则相反,它会跳过流中的元素,直到找到第一个满足给定谓词的元素,然后返回剩余的所有元素。

示例代码:

public static void main(String[] args) {  
    List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
  
    List<Integer> dropWhileList = numbers.stream()  
            .dropWhile(n -> n < 5)  
            .collect(Collectors.toList());  
  
    System.out.println("Drop while: " + dropWhileList);  
}

控制台输出

Drop while: [5, 6, 7, 8, 9, 10]

ofNullable 方法

ofNullable 方法允许你从一个可能为 null 的值创建一个 Stream,如果值不是 null,则创建一个单元素流;如果是 null,则创建一个空流。

示例代码:

public static void main(String[] args) {  
    Optional<String> optionalString = Optional.of("Hello World");  
  
    Stream<String> stream = Stream.ofNullable(optionalString.orElse(null));  
  
    stream.forEach(System.out::println);  
}

控制台输出

Hello World

iterate 方法

iterate 方法允许你基于一个初始值和一个迭代函数来创建无限流,Java 9 为 iterate 方法增加了一个重载版本,允许你指定一个终止条件。

示例代码

public static void main(String[] args) {  
    // 使用 iterate 创建一个无限流,直到达到 10  
    Stream<Long> infiniteStream = Stream.iterate(0L, n -> n + 1);  
  
    // 限制流的大小  
    Stream<Long> limitedStream = infiniteStream.limit(10);  
  
    limitedStream.forEach(System.out::println);  
  
    // 使用 iterate 的重载版本,直到终止条件为 true 
    Stream<Long> untilStream = Stream.iterate(0L, n -> n < 10, n -> n + 1);  
  
    untilStream.forEach(System.out::println);  
}

控制台输出

限制流的大小: 0 1 2 3 4 5 6 7 8 9 
终止条件为 true0 1 2 3 4 5 6 7 8 9

Optional 类的新方法

Java 9 为 Optional 类添加了一些新方法,如 ifPresentOrElseor

ifPresentOrElse

ifPresentOrElse 方法的作用是:如果Optional 中有值,则执行指定的操作;
如果没有值,则执行另一个操作。这个方法可以让我们在处理可选值时,避免使用多个if 语句,从而使代码更加简洁。

源码

void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
  • action :如果 Optional 中有值,则执行的操作。
  • emptyAction :如果 Optional 中没有值,则执行的操作。

示例代码

import java.util.Optional;

public class IfPresentOrElseExample {
    public static void main(String[] args) {
        // 有值的情况
        Optional<String> optionalValue = Optional.of("Hello, World!");
        optionalValue.ifPresentOrElse(
            value -> System.out.println("Value is present: " + value),
            () -> System.out.println("Value is absent")
        );

        // 没有值的情况
        Optional<String> emptyValue = Optional.empty();
        emptyValue.ifPresentOrElse(
            value -> System.out.println("Value is present: " + value),
            () -> System.out.println("Value is absent")
        );
    }
}

控制台

Value is present: Hello, World!
Value is absent

or

or 方法的作用是:如果 Optional 中有值,则返回该值;如果没有值,则返回另一个 Optional 。这个方法使得我们可以提供一个备用的值或 Optional ,从而避免 null 的情况。

源码

Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
  • supplier :如果 Optional 为空,则提供一个新的 Optional

示例代码

import java.util.Optional;

public class OrExample {
    public static void main(String[] args) {
        // 有值的情况
        Optional<String> optionalValue = Optional.of("Hello");
        String result1 = optionalValue.or(() -> Optional.of("Default Value")).get();
        System.out.println("Result 1: " + result1); // 输出: Hello

        // 没有值的情况
        Optional<String> emptyValue = Optional.empty();
        String result2 = emptyValue.or(() -> Optional.of("Default Value")).get();
        System.out.println("Result 2: " + result2); // 输出: Default Value
    }
}

控制台

Result 1: Hello
Result 2: Default Value

总结

  • ifPresentOrElse 方法允许我们在处理 Optional 时,优雅地处理有值和无值的情况。
  • or 方法则提供了一种方式来指定备用的 Optional 值,以便在原始 Optional 为空时使用。
    这两个方法的引入,使得 Optional 的使用更加灵活和方便,帮助开发者更好地处理可能缺失的值。

反应式流(Reactive Streams)

Java 9 引入了对反应式编程的支持,提供了 Flow 类,用于处理异步数据流。 Flow 类是 Java 反应式流(Reactive Streams)规范的一部分,允许开发者以非阻塞的方式处理数据流,并支持背压(backpressure)机制。

Flow 类的核心组件

  1. Publisher:发布数据流的对象。
  2. Subscriber:订阅数据流的对象,负责处理接收到的数据。
  3. Subscription:连接发布者和订阅者的桥梁,负责请求数据和控制数据流。
  4. Processor:既是发布者又是订阅者,负责在数据流中进行处理。

示例代码

import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;

/**  
 * 展示了如何使用 Flow 类创建一个发布者和一个订阅者。  
 */
public class ReactiveStreamsExample {
    public static void main(String[] args) {
        // 创建一个 SubmissionPublisher,作为发布者
        SubmissionPublisher<String> publisher = new SubmissionPublisher<>();

        // 创建一个订阅者
        Flow.Subscriber<String> subscriber = new Flow.Subscriber<>() {
            private Flow.Subscription subscription;

            @Override
            public void onSubscribe(Flow.Subscription subscription) {
                this.subscription = subscription;
                // 请求1个数据
                subscription.request(1);
            }

            @Override
            public void onNext(String item) {
                System.out.println("Received: " + item);
                // 处理完一个数据后,再请求下一个数据
                subscription.request(1);
            }

            @Override
            public void onError(Throwable throwable) {
                System.err.println("Error: " + throwable.getMessage());
            }

            @Override
            public void onComplete() {
                System.out.println("Processing complete.");
            }
        };

        // 将订阅者注册到发布者
        publisher.subscribe(subscriber);

        // 发布一些数据
        System.out.println("Publishing items...");
        for (int i = 1; i <= 5; i++) {
            publisher.submit("Item " + i);
        }

        // 关闭发布者
        publisher.close();
    }
}

代码解释

  1. SubmissionPublisher:这是一个实现了 Publisher 接口的类,允许我们手动提交数据。
  2. Subscriber:我们实现了 Flow.Subscriber 接口,定义了如何处理接收到的数据。
    • onSubscribe :当订阅者与发布者连接时调用,负责请求数据。
    • onNext :当接收到数据时调用,处理数据并请求下一个数据。
    • onError :处理错误情况。
    • onComplete :处理完成时的逻辑。
  3. 数据发布:我们在一个循环中发布了5个数据项,并在发布后关闭了发布者。

使用场景

  1. 实时数据处理
    • 在金融服务中,实时处理股票价格、交易数据等信息,反应式流可以帮助系统快速响应市场变化。
  2. 微服务架构
    • 在微服务架构中,各个服务之间通过消息队列进行通信。使用反应式流可以有效地处理来自不同服务的异步消息,提高系统的响应能力和可扩展性。
  3. Web 应用程序
    • 在高并发的 Web 应用中,反应式流可以用来处理用户请求,特别是当请求涉及到数据库查询或外部 API 调用时,可以避免阻塞主线程,提高用户体验。
  4. 数据流处理
    • 在数据分析和 ETL(提取、转换、加载)过程中,反应式流可以用于处理大量数据的流式传输和实时分析。
  5. 物联网(IoT)应用
    • 在物联网应用中,设备会不断生成数据,反应式流可以帮助处理这些数据流,进行实时监控和分析。
  6. 其他:
    • 结合当前的特性再应用到合适的场景中

总结

Java 9 的 Flow 类为开发者提供了一种强大的工具来处理异步数据流,支持非阻塞操作和背压机制。这使得反应式编程在现代应用中变得越来越重要,特别是在需要高并发、高可用性和实时处理的场景中。

JShell(交互式命令行工具)

JShell 是一个新的命令行工具,可以用来快速测试 Java 代码片段,而无需创建完整的 Java 程序。

//第一步 输入 jshell 进入 
PS D:\project\hot-sauce-2> jshell 
| 欢迎使用 JShell -- 版本 17.0.7 
| 要大致了解该版本, 请键入: /help intro 

//第二步 编写代码 
jshell> int sum(int a, int b) {
...> return a + b; 
...> } 
| 已创建 方法 sum(int,int) 


// 第三部 运行第二步代码,得到结果 
jshell> sum(5, 10) 
$2 ==> 15

接口中的私有方法

Java 9 允许在接口中声明私有方法,这可以用来实现共享逻辑。

示例代码

/**  
 * 接口  
 */  
public interface MyInterface {  
    // 私有方法  
    private void printMessage() {  
        System.out.println("This is a private method in an interface.");  
    }  
  
    // 默认方法  
    default void display() {  
        printMessage();  
    }  
}

/**  
 * 实现
 */  
public class MyClass implements MyInterface {  
    public static void main(String[] args) {  
        new MyClass().display();  
    }  
}

增强@Deprecated注解

在 Java 9 中, @Deprecated 注解得到了增强,提供了更多的信息以帮助开发者理解被弃用的 API 的状态。这一增强主要体现在两个新的元素的引入上:

1. forRemoval

  • 类型boolean
  • 说明:该元素指示被弃用的元素是否计划在未来的版本中移除。如果设置为 true ,表示这个元素在未来的某个版本中会被移除。这个信息对于开发者来说非常重要,因为它可以帮助他们决定是否应该立即迁移到替代方案。

2. since

  • 类型String
  • 说明:该元素用于指定自哪个版本开始该元素被弃用。这可以让开发者快速了解该 API 的弃用历史,从而更好地管理代码的兼容性。

代码示例

public class Example {
    /**
     * @deprecated This method is deprecated because it is inefficient.
     * It is recommended to use {@link #newMethod()} instead.
     * 
     * @since 9
     * @forRemoval true
     */
    @Deprecated(since = "9", forRemoval = true)
    public void oldMethod() {
        // old implementation
    }

    public void newMethod() {
        // new implementation
    }
}

在上面的示例中:

  • oldMethod 被标记为弃用,注解中包含了 since = "9" ,表示这个方法从 Java 9 开始被弃用。
  • forRemoval = true 表示这个方法计划在未来的版本中被移除。
  • 方法的文档注释中也建议使用 newMethod() 作为替代方案。

总结

Java 9 中对 @Deprecated 注解的增强使得开发者在使用被弃用的 API 时能够获得更多的上下文信息。这种增强有助于提高代码的可维护性,减少未来版本中的兼容性问题,促使开发者更早地迁移到更好的替代方案。通过明确标记弃用的原因和计划移除的时间,Java 9 使得 API 的管理变得更加清晰和高效。

CompletableFuture API

在 Java 9 中, CompletableFuture API 进行了多项增强,使得异步编程更加灵活和强大

1. 新的工厂方法

Java 9 引入了几个新的静态工厂方法,增强了 CompletableFuture 的创建和组合能力:

  • CompletableFuture.allOf(CompletableFuture<?>... futures)
    • 这个方法接受多个 CompletableFuture 对象,并在所有给定的 CompletableFuture 完成时完成。适用于需要等待多个异步任务完成的场景。
  • CompletableFuture.anyOf(CompletableFuture<?>... futures)
    • 这个方法接受多个 CompletableFuture 对象,并在其中任意一个完成时完成。适合用于需要在多个任务中选择第一个完成的任务的场景。
      示例代码
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            // 模拟耗时操作
            sleep(1000);
            return "Result from Future 1";
        });

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            sleep(2000);
            return "Result from Future 2";
        });

        // 使用 allOf 等待所有任务完成
        CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2);
        allOf.join(); // 阻塞直到所有任务完成

        // 输出结果
        System.out.println(future1.join());
        System.out.println(future2.join());

        // 使用 anyOf 等待任意一个任务完成
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2);
        System.out.println("First completed: " + anyOf.join());
    }

    private static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

2. 异常处理增强

Java 9 对异常处理的支持进行了增强,特别是与异常处理和组合相关的方法:

  • handle(BiFunction<? super T, Throwable, ? extends U> fn)
    • 这个方法允许你在计算完成时处理结果或异常。无论是正常完成还是异常完成,都会调用提供的函数。
  • exceptionally(Function<? super Throwable, ? extends T> fn)
    • 用于处理异常的函数,如果 CompletableFuture 在计算过程中发生异常,则会调用这个函数。
      示例代码
import java.util.concurrent.CompletableFuture;

public class CompletableFutureErrorHandlingExample {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 模拟异常
            if (true) throw new RuntimeException("Something went wrong!");
            return "Result";
        });

        future
            .handle((result, ex) -> {
                if (ex != null) {
                    System.out.println("发生错误: " + ex.getMessage());
                    return "备用结果";
                }
                return result;
            })
            .thenAccept(System.out::println);
    }
}

3. delayedExecutor 方法

Java 9 引入了 delayedExecutor 方法,允许你创建一个带有延迟的执行器,用于在指定的延迟后执行任务。

  • delayedExecutor(long delay, TimeUnit unit)
    • 返回一个 ExecutorService ,可以用来在指定的延迟后执行任务。
      示例代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

public class DelayedExecutorExample {
    public static void main(String[] args) {
        // 创建一个带有延迟的执行器
        ExecutorService executor = CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS);

        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("任务在延迟后执行");
        }, executor);

        // 等待任务完成
        future.join();
        System.out.println("主线程结束");
    }
}

4. 超时处理增强

Java 9 还增加了对超时处理的支持:

  • orTimeout(long timeout, TimeUnit unit)
    • 允许设置超时,如果在指定的时间内未完成,则会自动取消 CompletableFuture
  • completeOnTimeout(T value, long timeout, TimeUnit unit)
    • 允许在指定的超时时间内完成 CompletableFuture ,如果在超时之前没有完成,则会使用给定的值完成。

总结

Java 9 对 CompletableFuture 的增强使得异步编程更加灵活和强大,提供了更好的异常处理机制、组合方式和超时处理能力。通过新增的工厂方法和增强的方法,开发者可以更方便地处理并发任务,提高程序的响应性和可维护性。这些特性使得 CompletableFuture 成为处理异步编程的重要工具。

ProcessHandle 类增强

在 Java 9 中, ProcessHandle 类得到了增强,提供了一些新的特性和方法,使得对操作系统进程的管理和监控变得更加方便和高效。以下是 Java 9 中 ProcessHandle 的主要新特性:

1. 新增的静态方法

Java 9 引入了一些新的静态方法,使得获取当前进程的信息变得更加简单:

  • ProcessHandle.current()
    • 该方法返回当前 Java 进程的 ProcessHandle 实例。通过这个实例,开发者可以获取当前进程的 ID、状态等信息。

2. 进程信息获取

通过 ProcessHandle ,可以获取关于进程的多种信息:

  • pid()
    • 返回进程的唯一标识符(PID)。
  • info()
    • 返回一个 ProcessHandle.Info 对象,提供关于进程的详细信息,包括命令行、启动时间、用户等。
  • children()
    • 返回当前进程的子进程的 ProcessHandle 流。可以用于遍历当前进程的所有子进程。
  • parent()
    • 返回当前进程的父进程的 ProcessHandle (如果存在)。

3. 进程状态监控

Java 9 中的 ProcessHandle 提供了对进程状态的监控功能:

  • isAlive()
    • 检查进程是否仍在运行。

4. 进程终止

可以通过 ProcessHandle 来终止进程:

  • destroy()
    • 终止与该 ProcessHandle 关联的进程。

示例代码

import java.util.Optional;

public class ProcessHandleExample {
    public static void main(String[] args) {
        // 获取当前进程的 ProcessHandle
        ProcessHandle currentProcess = ProcessHandle.current();

        // 打印当前进程的 PID
        System.out.println("Current Process ID: " + currentProcess.pid());

        // 获取进程信息
        ProcessHandle.Info info = currentProcess.info();
        System.out.println("Command: " + info.command().orElse("N/A"));
        System.out.println("Arguments: " + info.arguments().map(argsArray -> String.join(", ", argsArray)).orElse("N/A"));
        System.out.println("User: " + info.user().orElse("N/A"));
        System.out.println("Start Time: " + info.startInstant().orElse(null));

        // 检查进程是否存活
        System.out.println("Is Alive: " + currentProcess.isAlive());

        // 获取子进程
        currentProcess.children().forEach(child -> {
            System.out.println("Child Process ID: " + child.pid());
        });

        // 获取父进程
        Optional<ProcessHandle> parentProcess = currentProcess.parent();
        parentProcess.ifPresent(parent -> {
            System.out.println("Parent Process ID: " + parent.pid());
        });
    }
}

总结

Java 9 中对 ProcessHandle 的增强使得开发者能够更加方便地管理和监控操作系统进程。通过新增的方法,开发者可以轻松获取进程的基本信息、监控进程状态、获取子进程和父进程的信息,以及终止进程。这些特性为 Java 应用程序提供了更强大的进程管理能力,特别是在需要与底层操作系统进行交互的场景中。

其他

多分辨率图像API、内部类操作符、改进了JavaDocs、多版本共存JAR 等想要了解的同学可以进一步研究,在实际项目中使用极少,这么就不展开说明了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值