Java 17
# 一、文本块
在Java 17版本之前,我们定义一个Json格式的字符串是按照如下方式:
public class Demo01 {
public static void main(String[] args) {
String text = "{\n" +
"\"name\":\"wxx\",\n" +
"\"age\":\"25\"\n" +
"}";
System.out.println(text);
}
}
- 双引号需要进行转义
- 为了字符串的可读性需要通过+号连接
- Json可读性差
通过Java 17的文本块语法,类似这样复杂的字符串处理就会方便很多,而且可读性也会更好。具体方式是通过三个双引号可以定义一个文本块,并且结束的三个双引号不能和开始的在同一行。
package demo;
/**
* 演示文本块
*/
public class Demo01 {
public static void main(String[] args) {
String text = """
{
"name":"wxx",
"age":"25"
}
""";
System.out.println(text);
}
}
# 二、switch表达式
在之前Java版本中,switch是根据给定的数值,进行一些逻辑判断:
public class Demo02 {
public static void main(String[] args) {
String fruit = "APPLE";
switch (fruit) {
case "APPLE":
System.out.println("普通水果");
break;
case "MANGO":
System.out.println("进口水果");
break;
default:
System.out.println("未知水果");
}
}
}
在Java 17版本可以对switch表达式进行简化,并且switch表达式默认不需要额外添加break,甚至我们还可以进行一下逻辑赋值操作:
public class Demo02 {
public static void main(String[] args) {
String fruit = "APPLE";
String result = switch (fruit) {
case "APPLE" -> "普通水果";
case "MANGO" -> "进口水果";
default -> "未知水果";
};
System.out.println(result);
}
}
# 三、record关键字
record用于创建不可变的数据类。在这之前如果你需要创建一个存放数据的类,通常需要先创建一个Class,然后生成构造方法、getter、setter、hashCode、equals和toString等这些方法,或者使用Lombok来简化这些操作。
现在有一个Person类:
package demo;
public class Person {
String name;
Integer age;
String address;
// 省略get和put和构造
}
由于toString()方法会将三个属性都进行输出,如果有些业务我们只需要输出两个属性,又不想通过字符串的方式:
public class Demo03 {
public static void main(String[] args) {
Person person = new Person("wxx", 25, "aaa");
System.out.println(person);
record PersonRecord(String name, Integer age){}
PersonRecord personRecord = new PersonRecord(person.getName(), person.getAge());
System.out.println(personRecord);
}
}
# 四、instanceof模式匹配
通常我们使用instanceof时,一般发生在需要对一个变量的类型进行判断,如果符合指定的类型,则强制类型转换为一个新变量。
public class Demo04 {
public static void main(String[] args) {
Person person = new Person("wxx", 25, "aaa");
Object object = (Object) person;
if (object instanceof Person) {
Person person1 = (Person) object;
System.out.println(person1);
}
}
}
在使用instanceof的模式匹配后,上面的代码可进行简写:
public class Demo04 {
public static void main(String[] args) {
Person person = new Person("wxx", 25, "aaa");
Object object = (Object) person;
if (object instanceof Person person1 && person1.getName().equals("wxx")) {
System.out.println(person1);
}
}
}
可以将类型转换和变量声明都在if中处理。同时,可以直接在if中使用这个变量。
# 五、Helpful NullPointerExceptions
Helpful NullPointerExceptions可以在我们遇到NPE时节省一些分析时间:
public static void main(String[] args) {
Person p = new Person();
String cityName = p.getAddress().getCity().getName();
}
在Java 11中,输出将显示NullPointerException发生的行号,但不知道哪个方法调用时产生的null,必须通过调试的方式找到。
Exception in thread "main" java.lang.NullPointerException
at com.heiz.java17.HelpfulNullPointerExceptionsDemo.main(HelpfulNullPointerExceptionsDemo.java:13)
在Java 17中,则会准确显示发生NPE的精确位置。
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.heiz.java17.Address.getCity()" because the return value of "com.heiz.java17.Person.getAddress()" is null
at com.heiz.java17.HelpfulNullPointerExceptionsDemo.main(HelpfulNullPointerExceptionsDemo.java:13)
# 六、日期周期格式化
在Java 17中添加了一个新的模式B
,用于格式化DateTime
,它根据Unicode
标准指示一天时间段。
使用默认的英语语言环境,打印一天的几个时刻:
public class Demo06 {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("B");
System.out.println(dtf.format(LocalTime.of(8, 0)));
System.out.println(dtf.format(LocalTime.of(13, 0)));
System.out.println(dtf.format(LocalTime.of(20, 0)));
System.out.println(dtf.format(LocalTime.of(23, 0)));
System.out.println(dtf.format(LocalTime.of(0, 0)));
}
}
in the morning
in the afternoon
in the evening
at night
midnight
# 七、精简数字格式化支持
在NumberFormat中添加了一个工厂方法,可以根据Unicode标准以紧凑的、人类可读的形式格式化数字。
SHORT格式
public class Demo07 {
public static void main(String[] args) {
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.ENGLISH, NumberFormat.Style.SHORT);
System.out.println(fmt.format(1000));
System.out.println(fmt.format(100000));
System.out.println(fmt.format(1000000));
}
}
1K
100K
1M
LONG格式
public class Demo07 {
public static void main(String[] args) {
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.ENGLISH, NumberFormat.Style.LONG);
System.out.println(fmt.format(1000));
System.out.println(fmt.format(100000));
System.out.println(fmt.format(1000000));
}
}
1 thousand
100 thousand
1 million
# 八、Stream.toList()
如果需要将Stream转换成List,需要通过调用collect方法使用Collectors.toList(),代码非常冗长。
public class Demo08 {
public static void main(String[] args) {
Stream<String> stringStream = Stream.of("a", "b", "c");
List<String> stringList = stringStream.collect(Collectors.toList());
for(String s : stringList) {
System.out.println(s);
}
}
}
在Java 17中将会变得简单,可以直接调用toList()
public class Demo08 {
public static void main(String[] args) {
Stream<String> stringStream = Stream.of("a", "b", "c");
List<String> stringList = stringStream.toList();
for(String s : stringList) {
System.out.println(s);
}
}
}
# 九、集合操作
- of() 方法:创建一个不可变的集合
List<String> list = List.of("apple", "banana", "orange");
Set<Integer> set = Set.of(1, 2, 3, 4);
Map<String, Integer> map = Map.of("apple", 1, "banana", 2, "orange", 3);
- forEach() 方法:遍历集合
List<String> list = List.of("apple", "banana", "orange");
list.forEach(name -> System.out.println(name));
Set<Integer> set = Set.of(1, 2, 3, 4);
set.forEach(number -> System.out.println(number));
- Collectors类:提供了一系列的归约操作
List<String> list = List.of("apple", "banana", "orange");
String joinedString = list.stream().collect(Collectors.joining("-", "[", "]"));
System.out.println(joinedString);
Map<String, Integer> map = Map.of("apple", 1, "banana", 2, "orange", 3);
Map<Integer, String> reversedMap = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
System.out.println(reversedMap);
- takeWhile() 方法和 dropWhile() 方法:根据条件截取集合
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7);
List<Integer> takenList = list.stream().takeWhile(number -> number < 5).collect(Collectors.toList());
System.out.println(takenList);
List<Integer> dropedList = list.stream().dropWhile(number -> number < 5).collect(Collectors.toList());
System.out.println(dropedList);
- toArray(IntFunction<T[]>) 方法:返回集合中的所有元素到一个新数组中
List<String> list = List.of("apple", "banana", "orange");
String[] array = list.toArray(String[]::new);
System.out.println(Arrays.toString(array));