Java 18
JEP 408:简单 Web 服务器
JEP 408: Simple Web Server
https://openjdk.org/jeps/408
The jwebserver Command
https://docs.oracle.com/en/java/javase/21/docs/specs/man/jwebserver.html
可以使用 jwebserver
命令启动一个简易的静态 Web 服务器。
从目标来说,提供了一个命令行工具来启动仅提供静态文件的最小 Web 服务器。
主要用于原型设计、临时编码和测试目的场景,具有简单的设置和最少的功能。
public static void main(String[] args) {
InetSocketAddress addr = new InetSocketAddress(8000);
HttpServer server = SimpleFileServer.createFileServer(
addr, Path.of(System.getProperty("user.dir")), SimpleFileServer.OutputLevel.INFO);
server.start();
}
等价于
jwebserver -p 8000 -d / -b 127.0.0.1 -o info
- -b:绑定地址
- -d:供服务的目录
- -o:输出级别
- -p:端口
JEP 413:Java API 文档中的代码片段
JEP 413: Code Snippets in Java API Documentation
https://openjdk.org/jeps/413
新增 @snipppet
标签。
在 Java 18 之前,如果要在 Javadoc 中引入代码片段,需要使用 <pre>{@code ...}</pre>
,使用上等同于文本编辑器。
/**
* The following code shows how to use {@code Optional.isPresent}:
* <pre>{@code
* if (v.isPresent()) {
* System.out.println("v: " + v.get()); * } * }
* </pre>
*/
使用 @snipppet
,在 IDE 中可以获得高亮与代码提示支持。
/**
* The following code shows how to use {@code Optional.isPresent}:
* {@snippet :
* if (v.isPresent()) {
* System.out.println("v: " + v.get());
* }
* }
*/
Java 21
常规方法增加
表请符号支持
Java 21中 在 Character 类中增加了用于确定字符是否为 Emoji 的方法。
https://bugs.openjdk.org/browse/JDK-8303018
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Character.html
https://unicode.org/reports/tr51/#Emoji_Properties_and_Data_Files
// 是否为 Emoji
public static boolean isEmoji(int codePoint)
// 是否为 Emoji 组件(具有标准中的定义的 Emoji_Component 属性)
public static boolean isEmojiComponent(int codePoint)
// Emoji 是否被修改(Emoji_Modifier 属性)
public static boolean isEmojiModifier(int codePoint)
// Emoji 是否可修改(Emoji_Modifier_Base 属性)
public static boolean isEmojiModifierBase(int codePoint)
// 确定指定字符默认情况下是否具有表情符号表示属性(Emoji_Presentation 属性)
public static boolean isEmojiPresentation(int codePoint)
// 确定指定字符是否是扩展象形文字(Extended_Pictographic 属性)
public static boolean isExtendedPictographic(int codePoint)
String msg1 = "Hey Java Developers! ☕️";
if (msg1.codePoints().anyMatch(Character::isEmoji)) {
System.out.println("Message contains an emoji");
}
String msg2 = "Hey Java Developers! 🙋🏻♂️";
OptionalInt emojiOptional = msg2.codePoints().filter(Character::isEmoji).findFirst();
if (emojiOptional.isPresent()) {
int emojiCodePoint = emojiOptional.getAsInt();
if (Character.isEmojiModifierBase(emojiCodePoint)) {
System.out.println("Emoji can be modified");
if (Character.isEmojiModifier(emojiCodePoint)) {
System.out.println("Emoji is modified");
} else {
System.out.println("Emoji has not been modified");
}
} else {
System.out.println("Emoji cannot be modified");
}
} else {
System.out.println("No emoji");
}
对 Emoji 的正则支持。
String msg1 = "Hey Java Developers! ☕️";
Matcher matcher1 = Pattern.compile("\\p{IsEmoji}").matcher(msg1);
if (matcher1.find()) {
System.out.println("Message contains an emoji!");
}
String msg2 = "Hey Java Developers! 🙋🏻♂️";
Matcher matcher2 = Pattern.compile("\\p{IsEmoji_Modifier_Base}").matcher(msg2);
if (matcher2.find()) {
System.out.println("Message contains an emoji modifier base!");
}
StringBuilder、StringBuffer 新增 repeat 方法
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/StringBuilder.html#repeat(int,int)
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/StringBuffer.html#repeat(int,int)
StringBuilder sb = new StringBuilder();
// CharSequence、int
sb.repeat('a', 5).repeat("str", 5);
System.out.println(sb);
JEP 431:有序集合
JEP 431: Sequenced Collections
https://openjdk.org/jeps/431
增加了三个新接口:
- SequencedCollection
- SequencedMap
- SequencedSet
在 JDK 21 之前,获取有序集合中第一个元素和最后一个元素的 api 并不统一,取决于具体类型。
First element | Last element | |
---|---|---|
List |
list.get(0) |
list.get(list.size() - 1) |
Deque |
deque.getFirst() |
deque.getLast() |
SortedSet |
sortedSet.first() |
sortedSet.last() |
LinkedHashSet |
linkedHashSet.iterator().next() |
// missing |
通过本次新增的三个接口,可以将相关调用进行统一。
JEP 440:Record 模式
JEP 440: Record Patterns
https://openjdk.org/jeps/440
现在可以对复杂嵌套的 Record 类解构,配合 instanceof 或 switch 使用。
interface Geometry { }
record Point(int x, int y) implements Geometry { }
record Size(int length, int width) implements Geometry { }
record Rectangle(Point point, Size size) implements Geometry { }
Point point = new Point(3, 7);
Size size = new Size(10, 5);
Object rectangle = new Rectangle(point, size);
if (rectangle instanceof Rectangle(Point p, Size(int l, int w))) {
System.out.println("(" + p.x + ", " + p.y + ")");
System.out.println("area = " + l * w);
}
switch (rectangle) {
case Point p -> System.out.println(p);
case Size s -> System.out.println(s);
case Rectangle(Point p, Size(int l, int w)) -> System.out.println("area = " + l * w);
default -> System.out.println("Unknown");
}
JEP 441:switch 模式匹配
JEP 441: Pattern Matching for switch
https://openjdk.org/jeps/441
对于不确定类型的对象判断时,可以用 switch 代替 instanceof。
for (Object obj : new Object[]{null, 1, 1L, 1.0, "str"}) {
String rst = switch (obj) {
// 可以判断 null
case null -> "null";
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("string %s", s);
default -> obj.toString();
};
System.out.println(rst);
}
JEP 444:虚拟线程