Java 13 特性

Java 13于2019年9月17日正式发布供生产使用。由于采用了6个月的发布周期,Java 13中没有太多面向开发者的特性。

Java 13特性

一些重要的Java 13特性包括:

  • 文本块 – JEP 355
  • 文本块中String类的新方法
  • Switch表达式增强 – JEP 354
  • 重新实现Legacy Socket API – JEP 353
  • 动态CDS存档 – JEP 350
  • ZGC:释放未使用的内存 – JEP 351
  • FileSystems.newFileSystem()方法
  • 支持Unicode 12.1
  • 具有命名空间支持的DOM和SAX工厂

如何启用预览特性

Switch表达式和文本块是预览特性。因此,您需要在项目中启用预览特性设置。如果您从命令行运行Java程序,可以使用--enable-preview开关启用它。您可以使用此开关启动具有启用预览特性的JShell。

$ jshell --enable-preview

$ java --enable-preview --source 13 Test.java

如果您使用Eclipse IDE,可以在项目的Java编译器设置中启用预览特性。

Eclipse Enable Preview Features

1. 文本块 – JEP 355

这是一个预览功能。它允许我们轻松创建多行字符串。多行字符串必须写在一对三重双引号之间。使用文本块创建的字符串对象没有额外的属性。这是创建多行字符串的一种更简单的方式。我们不能使用文本块创建单行字符串。开头的三重双引号后必须跟随一个换行符。

package com.journaldev.java13.examples;

public class TextBlockString {

	/**
	 * JEP 355: Preview Feature
	 */
	@SuppressWarnings("preview")
	public static void main(String[] args) {
		String textBlock = """
				Hi
				Hello
				Yes""";

		String str = "Hi\nHello\nYes";

		System.out.println("Text Block String:\n" + textBlock);
		System.out.println("Normal String Literal:\n" + str);

		System.out.println("Text Block and String Literal equals() Comparison: " + (textBlock.equals(str)));
		System.out.println("Text Block and String Literal == Comparison: " + (textBlock == str));
	}

}

输出:

Text Block String:
Hi
Hello
Yes
Normal String Literal:
Hi
Hello
Yes
Text Block and String Literal equals() Comparison: true
Text Block and String Literal == Comparison: true

在我们的Java程序中,它在轻松创建HTML和JSON字符串方面非常有用。

String textBlockHTML = """
		<html>
		<head>
			<link href='/css/style.css' rel='stylesheet' />
		</head>
		<body>
                        <h1>Hello World</h1>
                </body>
                </html>""";

String textBlockJSON = """
		{
			"name":"Pankaj",
			"website":"JournalDev"
		}""";

2. 字符串类中的新方法用于文本块

字符串类中有三个与文本块功能相关的新方法。

  1. formatted(Object… args): 它类似于String的format()方法。它被添加以支持在文本块中进行格式化。
  2. stripIndent(): 用于从文本块中的每一行的开头和结尾删除不必要的空白字符。此方法被文本块使用,并保留内容的相对缩进。
  3. translateEscapes(): 返回一个字符串,其值为此字符串,其中转义序列被转换,就像在字符串文字中一样。
package com.journaldev.java13.examples;

public class StringNewMethods {

	/***
	 * New methods are to be used with Text Block Strings
	 * @param args
	 */
	@SuppressWarnings("preview")
	public static void main(String[] args) {
		
		String output = """
			    Name: %s
			    Phone: %d
			    Salary: $%.2f
			    """.formatted("Pankaj", 123456789, 2000.5555);
		
		System.out.println(output);
		
		
		String htmlTextBlock = "<html>   \n"+
				                    "\t<body>\t\t \n"+
				                        "\t\t<p>Hello</p>  \t \n"+
				                    "\t</body> \n"+
				                "</html>";
		System.out.println(htmlTextBlock.replace(" ", "*"));
		System.out.println(htmlTextBlock.stripIndent().replace(" ", "*"));
		
		String str1 = "Hi\t\nHello' \" /u0022 Pankaj\r";
		System.out.println(str1);
		System.out.println(str1.translateEscapes());
		
	}

}

输出:

Name: Pankaj
Phone: 123456789
Salary: $2000.56

<html>***
	<body>		*
		<p>Hello</p>**	*
	</body>*
</html>
<html>
	<body>
		<p>Hello</p>
	</body>
</html>
Hi	
Hello' " /u0022 Pankaj
Hi	
Hello' " /u0022 Pankaj

3. Switch 表达式增强 – JEP 354

Switch 表达式在 Java 12 版本中作为预览功能添加。在 Java 13 中,除了将 “break” 替换为 “yield” 以从 case 语句返回值外,几乎相同。

package com.journaldev.java13.examples;

/**
 * JEP 354: Switch Expressions
 * https://openjdk.java.net/jeps/354
 * @author pankaj
 *
 */
public class SwitchEnhancements {

	@SuppressWarnings("preview")
	public static void main(String[] args) {
		int choice = 2;

		switch (choice) {
		case 1:
			System.out.println(choice);
			break;
		case 2:
			System.out.println(choice);
			break;
		case 3:
			System.out.println(choice);
			break;
		default:
			System.out.println("integer is greater than 3");
		}

		// 从 Java 13 开始 - 多标签 case 语句
		switch (choice) {
		case 1, 2, 3:
			System.out.println(choice);
			break;
		default:
			System.out.println("integer is greater than 3");
		}

		// switch 表达式,使用 yield 返回,在 Java 12 中是 break
		int x = switch (choice) {
		case 1, 2, 3:
			yield choice;
		default:
			yield -1;
		};
		System.out.println("x = " + x);

	}

	enum Day {
		SUN, MON, TUE
	};

	@SuppressWarnings("preview")
	public String getDay(Day d) {
		String day = switch (d) {
		case SUN -> "Sunday";
		case MON -> "Monday";
		case TUE -> "Tuesday";
		};
		return day;
	}
}

4. 重新实现传统套接字 API – JEP 353

java.net.Socket 和 java.net.ServerSocket API 的底层实现已被重写。新的实现,NioSocketImpl,是 PlainSocketImpl 的可插拔替代品。它使用 java.util.concurrent 锁而不是同步方法。如果要使用传统实现,请使用 Java 选项 -Djdk.net.usePlainSocketImpl

5. 动态CDS存档 – JEP 350

这个JEP扩展了在Java 10中引入的类数据共享功能。现在,创建CDS存档并使用它变得更容易了。

$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar

$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar

6. ZGC:释放未使用的内存 – JEP 351

这个JEP增强了ZGC,将未使用的堆内存归还给操作系统。Z垃圾收集器是在Java 11中引入的。它在清理堆内存之前增加了短暂的暂停时间。但是,未使用的内存并没有被归还给操作系统。这对于内存占用较小的设备,如物联网和微控制器,是一个问题。现在,它已经改进,可以将未使用的内存归还给操作系统。

7. FileSystems.newFileSystem() 方法

FileSystems类新增了三种新方法,以便更轻松地使用文件系统提供程序,这些方法将文件的内容视为文件系统。

  1. newFileSystem(Path)
  2. newFileSystem(Path,Map<String,?>)
  3. newFileSystem(Path,Map<String,?>,ClassLoader)

8. 带命名空间支持的DOM和SAX工厂

现在有了实例化带命名空间支持的DOM和SAX工厂的新方法。

  1. newDefaultNSInstance()
  2. newNSInstance()
  3. newNSInstance(String factoryClassName,ClassLoader classLoader)
//java 13及更高版本
DocumentBuilder db = DocumentBuilderFactory.newDefaultNSInstance().newDocumentBuilder(); 

// 在java 13之前
DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); 
dbf.setNamespaceAware(true); 
DocumentBuilder db = dbf.newDocumentBuilder();

结论

看起来,Java每6个月的发布效果很好。没有太多针对开发人员的特定功能,但总体而言这是一个很棒的发布。很高兴看到期待已久的文本块字符串支持。

参考资料

  • <文本块示例>

Source:
https://www.digitalocean.com/community/tutorials/java-13-features