首页 > 编程语言 >Java SE 18 新增特性

Java SE 18 新增特性

时间:2022-08-22 13:35:30浏览次数:78  
标签:Files UTF encoding 18 Java SE

Java SE 18 新增特性

作者:Grey

原文地址:Java SE 18 新增特性

源码

源仓库: Github:java_new_features

镜像仓库: GitCode:java_new_features

默认使用 UFT-8 编码

在 Java SE 18 之前的 Java中,标准字符集会因操作系统和语言设置的不同而不同。Java 标准字符集决定了在 JDK 类库的许多方法中如何将字符串转换为字节,反之亦然(例如,在写入和读取文本文件时)。这些方法包括:

  • FileReader, FileWriter, InputStreamReader, OutputStreamWriter的构造函数。

  • FormatterScanner的构造函数。

  • URLEncoder.encode()URLDecoder.decode()的静态方法。

当一个应用程序在一个环境中被开发和测试,然后在另一个环境中运行( Java 选择了不同的默认字符集),这可能导致不可预测的行为。

此外,由于较新的类库方法在没有指定字符集的情况下总是使用 UTF-8 ,所以变得更加混乱,例如:
Files.writeString(),Files.readString(),Files.newBufferedWriter()Files.newBufferedReader()

为了保护应用程序免受此类错误的影响,有两种解决方案:

方案一:在调用所有将字符串转换成字节的方法时指定字符集,反之亦然。

FileWriter fw = new FileWriter("happy-coding.txt", StandardCharsets.UTF_8);
// ...
FileReader fr = new FileReader("happy-coding.txt", StandardCharsets.UTF_8);
// ...
Files.readString(Path.of("happy-coding.txt"), StandardCharsets.UTF_8);

这个方案会导致大量的代码重复,容易出错。

方案二:通过系统属性 "file.encoding "设置默认字符集。

这种方案中的属性值在 Java SE 17 之前(包括 Java SE 17 )中没有正式记录(见system-properties)。

其次,如上所述,指定的字符集并不用于所有的 API 方法。比如:

public class Jep400Example {
  public static void main(String[] args) throws IOException {
    try (FileWriter fw = new FileWriter("happy-coding.txt");
        BufferedWriter bw = new BufferedWriter(fw)) {
      bw.write("ハッピーコーディング!");
    }

    String text = Files.readString(Path.of("happy-coding.txt"));
    System.out.println(text);
  }
}

让我们用标准编码 US-ASCII 来运行一次该程序。

java -Dfile.encoding=US-ASCII Jep400Example.java

运行结果如下

?????????????????????????????????

结果是垃圾,因为 FileWriter 考虑到了默认编码,但Files.readString()忽略了它,总是使用UTF-8。只有在你统一使用 UTF-8 的情况下才能正常运行。

java -Dfile.encoding=UTF-8 Jep400Example.java

运行结果如下

ハッピーコーディング!?

在 Java SE 18 中,无论操作系统、地域和语言设置如何,默认编码将始终是 UTF-8,见:JEP 400

另外,系统属性file.encoding也可以被合法使用。然而,我们应该谨慎地这样做。

最好的方法是将-Dfile.encoding设置为 UTF-8 或完全省略它。

代码示例

package git.snippets.jdk18;

import java.nio.charset.Charset;

public class UFT8Test {
    public static void main(String[] args) {
        System.out.println("Default charset : " + Charset.defaultCharset());
        System.out.println("file.encoding   : " + System.getProperty("file.encoding"));
        System.out.println("native.encoding : " + System.getProperty("native.encoding"));
        System.out.println(Charset.defaultCharset());
        System.out.println("你好");
    }
}

输出结果为:

Default charset : UTF-8
file.encoding   : UTF-8
native.encoding : GBK
UTF-8
你好

JDK 自带 Web Server

准备一个html页面,放到任意文件夹中,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Java自带的WebServer</title>
</head>
<body>
Web Server By JDK18
</body>
</html>

然后在这个文件所在目录执行

C:\jdk\jdk-18\bin\jwebserver.exe

启动后,控制台会打印如下信息

Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving C:\workspace\java_new_features\jdk18_features\src\main\resources and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/

访问http://127.0.0.1:8000/可以看到效果

image

API 文档注释中支持代码片段

如果我们想把多行代码片段集成到 JavaDoc 中,我们必须通过<pre>...</pre>来完成,而且必须与{@code ...}相结合,这样做非常麻烦

下面是一个使用<pre>标签的例子:

/**
 * How to write a text file with Java 7:
 *
 * <pre>{@code try (BufferedWriter writer = Files.newBufferedWriter(path)) {
 *  writer.write(text);
 *}}</pre>
 */

在 Java SE 18 中,引入了@snippet标签,可以用于代码片段的注释

/**
 * How to write a text file with Java 7:
 *
 * {@snippet :
 * try (BufferedWriter writer = Files.newBufferedWriter(path)) {
 *   writer.write(text);
 * }
 * }
 */

更多

Java SE 7及以后各版本新增特性

参考资料

JDK 18 Release Notes

Java18 新特性

New Features in Java 18

Java 18 Features (with Examples)

标签:Files,UTF,encoding,18,Java,SE
From: https://www.cnblogs.com/greyzeng/p/16612510.html

相关文章

  • ArcGIS API for JavaScript Editor Widget 选中多个要素不显示名称
    背景 最近升级时遇到了之前碰到的问题,但是忘记解决方法了。又重新对比了旧代码才找到,所以记录下。FeatureLayer的构建方式不是url,而是用的source环境 Vu......
  • Centos修改时区失败,Failed to set time zone: Failed to set time zone: Is a directo
    今日研发反馈有台测试机时区不对,但是无法修改,登录后发现修改报错,提示Failedtosettimezone:Failedtosettimezone:Isadirectory谷歌百度居然没有相同的报错,最......
  • JAVA中子类使用super.getClass()方法
    一般来说,java中调用getClass().getName()这个方法可以获取本类的名称,例如:importjava.util.Date;publicclassTest06extendsDate{publicstaticvoidmain(St......
  • 安装VMware——Unable to install all modules.See log /tmp/vmware-han/vmware-6098.
    这是编译失败的原因在VM社区有这样一种解决方案,亲测有效,帮助我自己解决的麻烦,所有在这分享,希望能够帮助到小伙伴:不要被接下来的代码吓倒因为这是github上项目,所以要先在ubu......
  • JAVA基础--数组--2022年8月21日
    第一节数组静态定义方式1、数组的静态初始化的写法和特点是什么样的?  2、数组属于什么类型,数组变量中存储的是什么?引用数据类型,存储的是......
  • Android文字基线Baseline算法的使用讲解
    引言Baseline是文字绘制时所参照的基准线,只有先确定了Baseline的位置,我们才能准确的将文字绘制在我们想要的位置上。Baseline的概念在我们使用TextView等系统控件直接设置......
  • Base64编码的原理
      Base64编码可以对字符串(中英文),字节集进行编码转换,核心思想就是3个字节一组进行处理,到最后不足3个字节,用00代替,被代替的用字符=来表示。下面举三个例子就能立马明白:例......
  • WebServer知识点梳理
    epollET模式(边缘触发)mysql(业务部分的内容)连接池(数据库)线程池日志定时器Reactor模式http大端序小端序互转hton读写缓冲区流程主线程监听连接主线程让epol......
  • Python中re、shutil、argparse库
    一、re库是关于正则表达式#后续用到再补充 二、shutil库作为os模块的补充,提供复制、移动、删除、解压等操作复制文件shutil.copy(src,dst)复制文件夹shutil.copyt......
  • Java实现BCD编码与十进制转换
    1、BCD码介绍BCD码(Binary-CodedDecimal‎)亦称二进码十进数或二-十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数码。是一种二进制的数字编码形式,用二进制编......