Java 12 的新特性
Oracle 于 2019 年 3 月 19 日发布了Java SE(标准版)12,之后他们计划每六个月发布一个新版本。 JDK 12 比 JDK 11 有很多改进。这个最新版本提供了一系列新功能,例如 Switch Expressions、默认 CDS Archives、Shenandoah、Microbenchmark Suite 等。下面将讨论这些新功能。
1. Switch 表达式的变化:
Switch 表达式现在将用作语句和表达式。这使得交换机的代码简化和模式匹配成为可能。
- 在早期版本中,缺少 break 语句会导致默认失败,这很容易出错。
- 默认情况在 switch 表达式中是强制性的。
现在,新的 switch 箭头语法引入为
case X -> {}
表示只有标签匹配,才会执行箭头右侧的语句。
Java 11 和Java 12 的 Switch 表达式可以比较如下:
Java11
Java
// Java program to demonstrate the
// classic switch statement
import java.io.*;
class Java11switchStatement {
static int getMealNumber(String meal)
{
// stores mealNumber
int mealNumber;
// classic switch statement
switch (meal) {
case "SOUP":
mealNumber = 1;
break;
case "BURGER":
case "CHIPS":
case "SANDWICH":
mealNumber = 2;
break;
case "SPAGETTI":
case "MACRONI":
mealNumber = 3;
break;
default:
throw new IllegalStateException(
"Cannot prepare " + meal);
}
return mealNumber;
}
public static void main(String[] args)
{
// define meal
String meal = "BURGER";
// print mealNumber
System.out.println("The mealNumber is : "
+ getMealNumber(meal));
}
}
Java
// Java program to demonstrate the
// new switch expression
import java.io.*;
class Java11switchStatement {
// returns mealNumber
static int getMealNumber(String meal)
{
// stores mealNumber using
// new switch expression
int mealNumber = switch (meal)
{
case "SOUP" -> 1;
case "BURGER", "CHIPS", "SANDWICH" -> 2;
case "SPAGETTI", "MACRONI" -> 3;
default -> throw new IllegalException("");
}
return mealNumber;
}
public static void main(String[] args)
{
// define meal
String meal = "BURGER";
// print mealNumber
System.out.println("The mealNumber is : "
+ getMealNumber(meal));
}
}
Java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class FilesCompareExample {
public static void main(String[] args)
throws IOException
{
Path path1 = Files.createTempFile("file1", ".txt");
Path path2 = Files.createTempFile("file2", ".txt");
Files.writeString(path1, "Geeks for geeks");
Files.writeString(path2, "Geeks for geeks");
long mismatch1 = Files.mismatch(path1, path2);
System.out.println(
"File Mismatch position or -1 is returned if there is no mismatch");
System.out.println(
"Mismatch position in file1 and file2 is : "
+ mismatch1);
path1.toFile().deleteOnExit();
path2.toFile().deleteOnExit();
System.out.println();
Path path3 = Files.createTempFile("file3", ".txt");
Path path4 = Files.createTempFile("file4", ".txt");
Files.writeString(path3, "Geeks for geeks");
Files.writeString(path4, "Geeks for the geeks");
long mismatch2 = Files.mismatch(path3, path4);
System.out.println(
"Mismatch position in file3 and file4 is : "
+ mismatch2);
path3.toFile().deleteOnExit();
path4.toFile().deleteOnExit();
}
}
Java
import java.text.NumberFormat;
import java.util.Locale;
public class CompactFormatExample {
public static void main(String[] args)
{
NumberFormat fmtLong
= NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.LONG);
System.out.println(fmtLong.format(100));
System.out.println(fmtLong.format(1000));
System.out.println(fmtLong.format(10000));
NumberFormat fmtShort
= NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.SHORT);
System.out.println(fmtShort.format(100));
System.out.println(fmtShort.format(1000));
System.out.println(fmtShort.format(10000));
}
}
Java
import java.io.*;
import java.util.*;
class TeeingCollectorsExample {
public static void main(String[] args)
{
double mean
= Stream.of(2, 3, 4, 5, 6)
.collect(Collectors.teeing(
summingDouble(i -> i), counting(),
(sum, n) -> sum / n));
System.out.println(mean);
}
}
The mealNumber is : 2
Java12
Java
// Java program to demonstrate the
// new switch expression
import java.io.*;
class Java11switchStatement {
// returns mealNumber
static int getMealNumber(String meal)
{
// stores mealNumber using
// new switch expression
int mealNumber = switch (meal)
{
case "SOUP" -> 1;
case "BURGER", "CHIPS", "SANDWICH" -> 2;
case "SPAGETTI", "MACRONI" -> 3;
default -> throw new IllegalException("");
}
return mealNumber;
}
public static void main(String[] args)
{
// define meal
String meal = "BURGER";
// print mealNumber
System.out.println("The mealNumber is : "
+ getMealNumber(meal));
}
}
输出
The mealNumber is : 2
2. Shenandoah(一个新的和改进的垃圾收集器)
这是一项实验性功能,并引入了一种新的垃圾回收 (GC) 算法 Shenandoah。它通过与运行的Java线程并发执行疏散工作来提供低暂停时间。这样,暂停时间与堆大小无关。例如,5MB 的堆与 10GB 的堆具有相同的暂停时间。
3. JVM 常量 API :这个 API 帮助那些操作类和方法的程序。这些程序需要对字节码指令进行建模并处理可加载的常量。 String 或 Integer 类型的常量工作正常。但是,将常量类型作为类变得棘手。如果 Class 不可访问或不存在,则加载类可能会失败。使用新的 API,ClassDesc、MethodTypeDesc、MethodHandleDesc 和 DynamicConstantDesc 等接口以符号方式处理常量值,从而消除了复杂性。
4. G1 的可中止混合收集:默认垃圾收集器 Garbage First (G1) 使用分析引擎来确定收集集,一旦收集开始,所有活动对象都应在不停止的情况下收集。这会导致超过目标暂停时间。为了解决这个问题,G1 集合集合通过将集合分解为可选部分和强制部分来中止。通过对强制设置进行优先级排序,可以经常实现暂停时间目标。
5. 默认 CDS 档案:创建类数据共享 (CDS) 档案以使 JDK 构建过程更高效,从而提高开箱即用的启动时间。
6. Microbenchmark 套件:开发人员可以通过添加到 JDK 源代码中的 microbenchmark 套件轻松运行现有或新的基准测试。
7. 及时从 G1 返回未使用的已提交内存:有了这个改进的功能,当 G1 空闲时,垃圾收集器会自动将未使用的堆内存返回给操作系统。这是通过 G1 并发检查Java堆来完成的。
8) Files.mismatch() 方法:这个新方法比较两个文件。
方法签名
public static long mismatch(Path path1, Path path2) throws IOException
返回: -1L如果没有不匹配 else第一个不匹配的位置。
在两种情况中的任何一种情况下,它都会返回不匹配的位置。
- 情况 1 :如果文件的大小不匹配。这里,返回较小文件的大小。
- 情况 2 :如果字节不匹配。在这里,返回第一个不匹配的字节。
例子:
Java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class FilesCompareExample {
public static void main(String[] args)
throws IOException
{
Path path1 = Files.createTempFile("file1", ".txt");
Path path2 = Files.createTempFile("file2", ".txt");
Files.writeString(path1, "Geeks for geeks");
Files.writeString(path2, "Geeks for geeks");
long mismatch1 = Files.mismatch(path1, path2);
System.out.println(
"File Mismatch position or -1 is returned if there is no mismatch");
System.out.println(
"Mismatch position in file1 and file2 is : "
+ mismatch1);
path1.toFile().deleteOnExit();
path2.toFile().deleteOnExit();
System.out.println();
Path path3 = Files.createTempFile("file3", ".txt");
Path path4 = Files.createTempFile("file4", ".txt");
Files.writeString(path3, "Geeks for geeks");
Files.writeString(path4, "Geeks for the geeks");
long mismatch2 = Files.mismatch(path3, path4);
System.out.println(
"Mismatch position in file3 and file4 is : "
+ mismatch2);
path3.toFile().deleteOnExit();
path4.toFile().deleteOnExit();
}
}
输出
Mismatch position in file1 and file2 is : -1
Mismatch position in file3 and file4 is : 10
9) Compact Number Formatting : 它是应用于通用数字的格式,例如小数、货币、百分比,以使其由于空间限制而变得紧凑。在下面的示例中,1000 在短样式中将被格式化为“1K”,在长样式中将被格式化为“1000”。
Java
import java.text.NumberFormat;
import java.util.Locale;
public class CompactFormatExample {
public static void main(String[] args)
{
NumberFormat fmtLong
= NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.LONG);
System.out.println(fmtLong.format(100));
System.out.println(fmtLong.format(1000));
System.out.println(fmtLong.format(10000));
NumberFormat fmtShort
= NumberFormat.getCompactNumberInstance(
Locale.US, NumberFormat.Style.SHORT);
System.out.println(fmtShort.format(100));
System.out.println(fmtShort.format(1000));
System.out.println(fmtShort.format(10000));
}
}
输出
100
1 thousand
10 thousand
100
1K
10K
10) Stream API 中的Teeing 收集器:Collectors.teeing() 是新的辅助函数,有助于将两步函数合并为一个步骤。这会减少冗长的代码。
方法签名
public static Collector teeing (Collector downstream1, Collector downstream2, BiFunction merger);
在这里,我们在两个不同的收集器上执行两个不同的流操作,并使用提供的BiFunction合并结果。
例子:
Java
import java.io.*;
import java.util.*;
class TeeingCollectorsExample {
public static void main(String[] args)
{
double mean
= Stream.of(2, 3, 4, 5, 6)
.collect(Collectors.teeing(
summingDouble(i -> i), counting(),
(sum, n) -> sum / n));
System.out.println(mean);
}
}
输出
4.0
11) Java String 新方法: Java 12 在 String 类中引入了以下新方法:
i) indent(int n) :它根据传递的参数调整给定字符串的每一行的缩进。
根据传递的n值,我们可以有以下几种情况:
- 如果n > 0 ,则在每行开头插入空格
- 如果n < 0 ,则在每行的开头删除空格
- 如果n < 0和n < 可用空格,则删除所有前导空格
- 如果n = 0 ,行保持不变
String str = "**********\n Welcome\n Good Morning\n**********";
System.out.println(str.indent(0));
System.out.println(str.indent(3));
输出
**********
Welcome
Good Morning
**********
**********
Welcome
Good Morning
**********
**********
Welcome
Good Morning
**********
ii) transform(函数 super String, ? extends R> f) :它用于调用一个需要字符串参数并产生结果 R 的函数。
String s = "Java,Python,Angular";
List result = s.transform(s1 -> {return Arrays.asList(s1.split(","));});
System.out.println(result);
输出
[Java, Python, Angular]
iii) Optional
String message = "Welcome!";
Optional opOfMessage = message.describeConstable();
System.out.println(opOfMessage);
输出
Optional[Welcome!]
iv) String resolveConstantDesc (MethodHandles.Lookup lookup) :此方法将返回一个 String 对象,它是调用 String 实例的描述符。
String message = "Welcome!";
String constantDesc = message.resolveConstantDesc(MethodHandles.lookup());
System.out.println(constantDesc);
输出
Welcome!
尽管与Java 8 相比, Java 12 尚未普及,但更频繁地添加新功能仍然使Java可以与其他语言的更好功能相媲美,从而保持其在市场上的受欢迎程度。