# Java 9 – 精简字符串改进 [JEP 254]

> 原文： [https://howtodoinjava.com/java9/compact-strings/](https://howtodoinjava.com/java9/compact-strings/)

直到 Java 8，Java 中的[字符串](https://docs.oracle.com/javase/9/docs/api/java/lang/String.html)内部都由`char[]`表示。 每个`char`都以 2 个字节存储在内存中。 oracle 的 JDK 开发人员分析了许多客户端的应用程序堆转储，他们注意到大多数字符串只能使用 [Latin-1 字符集](https://cs.stanford.edu/~miles/iso8859.html)表示。 拉丁 1 个字符可以存储在一个字节中，比`char`数据类型存储少 50%（1 个字节）。

因此，JDK 开发人员将`String`类的内部存储从`char[]`缺省设置为`byte[]`。 通常，这导致节省了堆内存的大量空间，因为字符串对象实际上占据了堆内存的很大一部分。（[来源](http://cr.openjdk.java.net/~shade/density/state-of-string-density-v1.txt)）

您可以使用`java`命令的`-XX:-CompactStrings`参数来控制应用程序中此特性的使用。

## Java 9 之前的字符串类

在 Java 9 之前，字符串数据存储为`char`数组。 每个字符需要 16 位。

```java
public final class String
   	implements java.io.Serializable, Comparable<String>, CharSequence {

   	//The value is used for character storage.
	private final char value[];

}

```

## Java 9 之后的字符串类

从 Java 9 开始，现在使用字节数组以及用于编码引用的标志字段在内部表示字符串。

```java
public final class String
   	implements java.io.Serializable, Comparable<String>, CharSequence {

    /** The value is used for character storage. */
	@Stable
	private final byte[] value;

	/**
	 * The identifier of the encoding used to encode the bytes in
	 * {@code value}. The supported values in this implementation are
	 *
	 * LATIN1
	 * UTF16
	 *
	 * @implNote This field is trusted by the VM, and is a subject to
	 * constant folding if String instance is constant. Overwriting this
	 * field after construction will cause problems.
	 */
	private final byte coder;

}

```

## `java`命令参考

众所周知，`java`命令用于启动 Java 应用程序。 它可以具有许多参数来定制应用程序运行时。 下面是一个这样的命令：

#### `-XX:-CompactStrings`

**禁用精简字符串特性**。 默认情况下，启用此选项。 启用此选项后，内部仅包含单字节字符的 Java 字符串将使用 ISO-8859-1/Latin-1 编码在内部表示并存储为每个字符的单字节字符串。 这将只包含单字节字符的字符串减少了 50% 的空间。 对于包含至少一个多字节字符的 Java 字符串：这些字符串使用 UTF-16 编码表示并存储为每个字符 2 个字节。 **禁用精简字符串特性将强制使用 UTF-16 编码**作为所有 Java 字符串的内部表示。

禁用精简字符串可能有益的情况包括：

1.  当知道应用程序将大量分配多字节字符字符串时
2.  在从 Java SE 8 迁移到 Java SE 9 的过程中观察到性能下降的意外事件中，分析表明精简字符串引入了回归。

在这两种情况下，禁用精简字符串都是有意义的。

这纯粹是实现更改，不更改现有的公共接口。

将我的问题放在评论部分。

学习愉快！