共计 2802 个字符,预计需要花费 8 分钟才能阅读完成。
默认应用 UFT-8 编码
在 Java SE 18 之前的 Java 中,规范字符集会因操作系统和语言设置的不同而不同。Java 规范字符集决定了在 JDK 类库的许多办法中如何将字符串转换为字节,反之亦然(例如,在写入和读取文本文件时)。这些办法包含:
FileReader
,FileWriter
,InputStreamReader
,OutputStreamWriter
的构造函数。Formatter
和Scanner
的构造函数。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)中没有正式记录
其次,如上所述,指定的字符集并不用于所有的 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
另外,零碎属性 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/
能够看到成果
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);
* }
* }
*/