Java 13功能

Java 13 在2019年9月17日发布,可用于生产环境。由于6个月的发布周期,Java 13中并没有很多针对开发者的特性。

Java 13功能

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

  • Text Blocks – JEP 355
  • New Methods in String Class for Text Blocks
  • Switch Expressions Enhancements – JEP 354
  • Reimplement the Legacy Socket API – JEP 353
  • Dynamic CDS Archive – JEP 350
  • ZGC: Uncommit Unused Memory – JEP 351
  • FileSystems.newFileSystem() Method
  • Support for Unicode 12.1
  • DOM and SAX Factories with Namespace Support

如何启用预览功能

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

$ jshell --enable-preview

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

如果你正在使用Eclipse IDE,你可以在项目的Java编译器设置中启用预览功能。

Eclipse Enable Preview Features

文本块 – JEP 355

文本块 – JEP 355

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

package com.Olivia.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. 字符串类中针对文本块的新方法

String类中有三种与文本块功能相关的新方法。

    1. formatted(Object… args):这与String类的format()方法相似。它用于支持使用文本块进行格式化。

 

    1. stripIndent():用于从文本块的每行开头和结尾移除附带的空白字符。该方法由文本块使用,并保留内容的相对缩进。

 

    translateEscapes():返回一个字符串,其值是将所有转义序列翻译为字符串文字中类似的形式的该字符串的值。
package com.Olivia.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());
		
	}

}

输出:请用中文将以下内容进行改述,只需要一个选项:

One possible paraphrase in Chinese:请以汉语完成以下内容的改述,只需要一个选项:

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. 代码表达式增强- JEP 354

在Java 12发布中,作为预览功能,引入了Switch表达式。在Java 13中几乎相同,只是将“break”替换为“yield”以从case语句中返回一个值。

package com.Olivia.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");
		}

		// from java 13 onwards - multi-label case statements
		switch (choice) {
		case 1, 2, 3:
			System.out.println(choice);
			break;
		default:
			System.out.println("integer is greater than 3");
		}

		// switch expressions, use yield to return, in Java 12 it was 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;
	}
}

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

java.net.Socket和java.net.ServerSocketAPI的底层实现已经被重写。新的实现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. 新建文件系统(Path)

 

    1. 新建文件系统(Path, Map<String, ?>)

 

    新建文件系统(Path, Map<String, ?>, ClassLoader)

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

有新的方法来实例化具有命名空间支持的DOM和SAX工厂。

    1. 创建默认的命名空间实例。

 

    1. 创建命名空间实例。

 

    创建命名空间实例,并指定工厂类名和类加载器。
//java 13 onwards
DocumentBuilder db = DocumentBuilderFactory.newDefaultNSInstance().newDocumentBuilder(); 

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

结论为

看起来,Java每六个月发布一次的模式一直表现良好。虽然没有太多专门针对开发者的功能,但总体而言,这是一个很棒的版本。看到大家期待已久的文本块字符串支持确实是一件好事。

参考文献

  • JDK 13 Release Notes
  • OpenJDK 13 Download Page
  • Text Blocks Examples
  • Eclipse.org Java 13 Examples