java11学习笔记

发布于:2025-08-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

var增强

对比与上版本,var可以使用的情况增多

(var a, var b) -> a + b;

String增强

新增Api

isBlank() 检查字符串是否为空或仅包含空白字符
lines() 分割获取字符串流(Stream)
strip() 去除字符串首尾的空白字符
repeat(n)

复制字符串 n复制次数

isBlank()

该方法是对isEmpty()的补充,isEmpty() 只能检查字符串长度是否为0,而isBlank()则回进一步检查了字符串的内容是否也只包含空白字符(换行)。

        System.out.println( "".isBlank());   // true
        System.out.println( " ".isBlank());   // true
        System.out.println( " \n\t ".isBlank());  // true
        System.out.println( "法外狂徒张三牛b".isBlank());  // false
lines()

该方法返回一个流(Stream),该流由字符串中的行组成,使用行结束符(适用于各种平台)作为分隔符。

        "法外狂徒张三".lines().forEach(System.out::println);
        "法外\r\n狂徒\n张三".lines().forEach(System.out::println);

strip()

对trim()的增强,trim()不能去掉全角空格和Unicode空白字符,strip()可以

stripLeading():仅移除开头的空白字符。

stripTrailing():仅移除末尾的空白字符。

        // 全角
        System.out.println("strip[全角]          :" + "[" + " 狂徒 张三 ".strip() + "]"); //strip[全角]          :[狂徒 张三]
        System.out.println("trim[全角]           :" + "[" + " 狂徒 六书 ".trim() + "]"); //trim[全角]           :[ 狂徒 六书 ]]
        // Unicode空白字符
        char ch = '\u2000'; // Unicode空白字符
        System.out.println("strip[Unicode空白字符]:" + "[" + (ch + "狂徒 张三" + ch).strip() + "]");//strip[全角]          :[狂徒 张三]
        System.out.println("trim[Unicode空白字符] :" + "[" + (ch + "狂徒 张三" + ch).trim() + "]");//trim[Unicode空白字符] :[ 狂徒 张三 ]
        // 半角
        System.out.println("strip[半角]          :" + "[" + " 狂徒 张三 ".strip() + "]");//strip[全角]          :[狂徒 张三]
        System.out.println("trim[半角]           :" + "[" + " 狂徒 张三 ".trim() + "]");//trim[tab键、换行符]   :[狂徒 张三]
        // tab键、换行符
        System.out.println("strip[tab键、换行符]  :" + "[" + "\n狂徒 张三\t".strip() + "]");//strip[全角]          :[狂徒 张三]
        System.out.println("trim[tab键、换行符]   :" + "[" + "\n狂徒 张三\t".trim() + "]");//trim[tab键、换行符]   :[狂徒 张三]
        System.out.println("strip[Unicode空白字符]:" + "[" + (ch + "狂徒 张三" + ch).stripLeading() + "]");//strip[全角]          :[狂徒 张三 ]
        System.out.println("strip[Unicode空白字符]:" + "[" + (ch + "狂徒 张三" + ch).stripTrailing() + "]");//strip[全角]          :[ 狂徒 张三]
repeat(n)
n< 0 1IllegalArgumentException =0"" =1 返回自身 >1 返回n个字符串本身
public String repeat(int count) {
    if (count < 0) {
        throw new IllegalArgumentException("count is negative: " + count);
    }
    if (count == 1) {
        return this;
    }
    final int len = value.length;
    if (len == 0 || count == 0) {
        return "";
    }
    if (len == 1) {
        final byte[] single = new byte[count];
        Arrays.fill(single, value[0]);
        return new String(single, coder);
    }
    if (Integer.MAX_VALUE / count < len) {
        throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
                " times will produce a String exceeding maximum size.");
    }
    final int limit = len * count;
    final byte[] multiple = new byte[limit];
    System.arraycopy(value, 0, multiple, 0, len);
    int copied = len;
    for (; copied < limit - copied; copied <<= 1) {
        System.arraycopy(multiple, 0, multiple, copied, copied);
    }
    System.arraycopy(multiple, 0, multiple, copied, limit - copied);
    return new String(multiple, coder);
}
        System.out.println("repeat".repeat(0));//""
        System.out.println("repeat".repeat(1));//"repeat"
        System.out.println("repeat".repeat(4));//"repeatrepeatrepeatrepeat"
        System.out.println("repeat".repeat(-1));//Exception in thread "main" java.lang.IllegalArgumentException: count is negative: -1

常量池加入String 

结果就是终于可以使用==判断字符串相等了

        String Str1="Hello World";
        String Str2="Hello World";
        System.out.println(Str1.equals(Str2));//true
        System.out.println(Str1==Str2);//true

新增Files API

Java 11 对java.nio.file.Files新增了三个 API:

  • readString():读取文件内容
  • writeString():写入文件内容
  • isSameFile():比较两个路径是否指向文件系统中的同一个文件

readString()

该方法可以将字符串写入文件中。

        Path path = Paths.get("file.txt");
        String content = "使用比例‌:约45%-50%(企业升级首选过渡版本)‌关键改进‌:模块化系统( JPMS )、内置 HTTP Client API 、 TLS 1.3 支持、移除 Java EE 和 CORBA 模块";
        Files.writeString(path, content);
//      Files.writeString(path, content, StandardCharsets.UTF_8);

writeString()

该方法可以读取文件的全部内容,返回一个字符串

        Path path = Paths.get("file.txt");
        System.out.println(Files.readString(path));
        System.out.println(Files.readString(path, StandardCharsets.UTF_8));

isSameFile()

该方法用于比较两个路径是否指向文件系统中的同一个文件,可以用来检查符号链接或文件快捷方式是否指向同一个文件。

        Path path1 = Paths.get("file.txt");
        Path path2 = Paths.get("file.txt");
        Path path3 = Paths.get("javaStudy.iml");
        System.out.println(Files.isSameFile(path1, path2));//true
        System.out.println(Files.isSameFile(path1, path3));//false

标准 HTTP Client 升级

在Java 9的时候,引入了一个新的HTTP客户端API(HttpClient)作为作为实验特性,到了 Java 11,则被标准化并正式成为Java标准库的一部分。经过前面两个版本中的孵化,Http Client 几乎被完全重写,并且现在完全支持异步非阻塞。新版 Java 中,Http Client 的包名由 jdk.incubator.http 改为java.net.http,该 API 通过 CompleteableFutures 提供非阻塞请求和响应语义。

全新的 HTTP 客户端 API 具有如下几个优势:

  1. HTTP/2支持:全新的 HttpClient 支持 HTTP/2 协议的所有特性,包括同步和异步编程模型。
  2. WebSocket支持:支持WebSocket,允许建立持久的连接,并进行全双工通信。
  3. 同步和异步:提供了同步和异步的两种模式。这意味着我们既可以等待HTTP响应,也可以使用回调机制处理HTTP响应。
  4. 链式调用:新的HttpClient 允许链式调用,使得构建和发送请求变得更简单。
  5. 更好的错误处理机制:新的HttpClient 提供了更好的错误处理机制,当HTTP请求失败时,可以通过异常机制更清晰地了解到发生了什么。
        HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString("{\n" +
                "  \"query\": \"法外狂徒张三\",\n" +
                "  \"cacheKey\": \"pc_right_follow_18011471021125571335\"\n" +
                "}");
        HttpClient client = HttpClient.newHttpClient();
                HttpRequest request = HttpRequest.newBuilder()
                        .uri(new java.net.URI("https://chat.baidu.com/aichat/api/follow_card?query=%E6%B3%95%E5%A4%96%E7%8B%82%E5%BE%92%E5%BC%A0%E4%B8%89&token=439c7b029270a1160b11e67e9d68239a"))
                        .POST(bodyPublisher)
                        .header("Accept", "application/vnd.github.v3+json")
                        .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("Response Code: " + response.statusCode());
                System.out.println("Response Body: " + response.body());

异步

        HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString("{\n" +
                "  \"query\": \"法外狂徒张三\",\n" +
                "  \"cacheKey\": \"pc_right_follow_18011471021125571335\"\n" +
                "}");
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(new java.net.URI("https://chat.baidu.com/aichat/api/follow_card?query=%E6%B3%95%E5%A4%96%E7%8B%82%E5%BE%92%E5%BC%A0%E4%B8%89&token=439c7b029270a1160b11e67e9d68239a"))
                .POST(bodyPublisher)
                .header("Accept", "application/vnd.github.v3+json")
                .build();
        System.out.println("哈哈哈");
        CompletableFuture<Void> voidCompletableFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(stringHttpResponse ->  stringHttpResponse)
                .thenAccept(stringHttpResponse -> {
                    System.out.println(stringHttpResponse.statusCode());
                    System.out.println(stringHttpResponse.body());
                });
        System.out.println("哈哈哈");
        voidCompletableFuture.join();

运行单文件源码程序

这项特性允许开发者直接运行一个包含源代码的单个Java文件,而无需事先将其编译成字节码。

此功能允许使用 Java 解释器直接执行 Java 源代码。

源代码在内存中编译,然后由解释器执行。但是有个限制条件是所有相关的类必须定义在同一个 Java 文件中。

直接使用java  [类文件名称(需加后缀.java)]

ZGC:可伸缩低延迟垃圾收集器

Z垃圾收集器,也称为ZGC,是一种可扩展的低延迟垃圾收集器。它旨在实现以下目标:

暂停时间不超过10毫秒

暂停时间不会随着堆或活动集的大小而增加

处理大小从几百兆字节到数万亿字节不等的堆

ZGC的核心是一个并发垃圾收集器,这意味着所有繁重的工作(标记、压缩、引用处理、字符串表清理等)都是在Java线程继续执行的同时完成的。这大大限制了垃圾回收对应用程序响应时间的负面影响。

ZGC作为一个实验特性被包括在内。因此,要启用它,-XX:+UnlockExperimentalVMOptions选项需要与-XX:+UseZGC选项结合使用。

ZGC的这个实验版本有以下限制:

它仅在Linux/x64上可用。

不支持使用压缩的oop和/或压缩的类点。默认情况下,-XX:+UseCompressedOops-XX:+UseCompressedClassPointers选项处于禁用状态。启用它们不会有任何效果。

不支持类卸载。默认情况下,-XX:+ClassUnloading-XX:+CClassUnloadingWithConcurrentMark选项处于禁用状态。启用它们不会有任何效果。

不支持将ZGC与Graal结合使用。

移除 Java EE和CORBA模块

移除的模块

java.xml.ws (JAX-WS, plus the related technologies SAAJ and Web Services Metadata)

java.xml.bind (JAXB,XML到Java对象的绑定)

java.activation (JAF)

java.xml.ws.annotation (服务注解)

java.corba (CORBA)

java.transaction (JTA)

java.se.ee (Aggregator module for the six modules above)

jdk.xml.ws (Tools for JAX-WS)

jdk.xml.bind (Tools for JAXB)

废弃 Nashorn JavaScript 引擎

弃用Nashorn JavaScript脚本引擎和API以及jjs工具,在未来的版本中将删除它们。

Nashorn JavaScript引擎实现、API和jjs shell工具已被弃用,可能会在未来的版本中删除。使用jdk.nashorn.api.scriptingjdk.naskorn.api.tree包中的类和接口的代码将从javac获得弃用警告。

Nashorn引擎(当被javax.script APIjrunscript工具使用时)以及jjs shell工具将打印关于弃用的警告消息。要禁用此运行时警告消息,用户可以包含新的Nashorn选项--no-deprecation-warning。这对于依赖于精确输出的兼容性脚本可能很有用(例如,避免警告破坏其预期的精确输出)。

Nashorn JavaScript引擎最初是在JDK 8 中引入的,用于取代Rhino脚本引擎,它允许在JVM上执行和调用JavaScript代码。

Java 11废弃Nashorn JavaScript引擎的主要原因是因为它难以跟上现代JavaScript发展的步伐,同时Oracle决定将资源集中在Java核心功能上,而不是维护与Java生态系统关联不大的组件,鼓励开发者转而使用更专注的JavaScript运行时环境,如Node.js

飞行记录器

飞行记录器(Flight Recorder) 之前是Oracle JDK 中的商业插件,但在 Java 11 中,其代码被包含到公开代码库中,这样所有人都能使用该功能了。

JFR (Java Flight Recorder)是一种分析工具,用于从正在运行的 Java 应用程序中收集诊断和分析数据。它的性能开销可以忽略不计,通常低于 1%。 因此它可以用于生产应用程序。

Java 语言中的飞行记录器类似飞机上的黑盒子,是一种低开销的事件信息收集框架,主要用于对 应用程序和 JVM 进行故障检查、分析。飞行记录器记录的 主要数据源于应用程序、JVM 和 OS,这些事件信息 保存在单独的事件记录文件中,故障发生后,能够从事件记录文件中 提取出有用信息 对故障进行分析。

启用飞行记录器参数如下:

-XX:StartFlightRecording

也可以使用jdkbin目录下的jcmd工具启动和配置飞行记录器:

飞行记录器启动、配置参数示例

$ jcmd <pid> JFR.start
$ jcmd <pid> JFR.dump filename=recording.jfr
$ jcmd <pid> JFR.stop

JFR 使用测试:

public class FlightRecorderTest extends Event {
    @Label("Hello World")
    @Description("Helps the programmer getting started")
    static class HelloWorld extends Event {
        @Label("Message")
        String message;
    }
 
    public static void main(String[] args) {
        HelloWorld event = new HelloWorld();
        event.message = "hello, world!";
        event.commit();
    }
}

在运行时加上如下参数:

java -XX:StartFlightRecording=duration=1s, filename=recording.jfr

下面读取上一步中生成的 JFR 文件:recording.jfr

飞行记录器分析示例

public void readRecordFile() throws IOException {
    final Path path = Paths.get("D:\\java\\recording.jfr");
    final List<RecordedEvent> recordedEvents = RecordingFile.readAllEvents(path);
    for (RecordedEvent event : recordedEvents) {
        System.out.println(event.getStartTime() + "," + event.getValue("message"));
    }
}

收集到的JFR记录文件可以使用多种工具进行分析,最常用的是JDK Mission Control(JMC)。JMC提供了一个图形界面,用于查看和分析JFR产生的数据文件。


网站公告

今日签到

点亮在社区的每一天
去签到