Каково внутреннее представление Java для String? Модифицированный UTF-8? UTF-16?

Я искал внутреннее представление Java для String, но у меня есть два материала, которые выглядят надежными, но несовместимыми.

Один:

http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.php/c10451

и это говорит:

Java использует UTF-16 для внутреннего текстового представления и поддерживает нестандартную модификацию UTF-8 для сериализации строк.

Другой это:

http://en.wikipedia.org/wiki/UTF-8

и это говорит:

Tcl также использует тот же модифицированный UTF-8[25], что и Java, для внутреннего представления данных Unicode, но использует строгий CESU-8 для внешних данных.

Модифицированный UTF-8? Или UTF-16? Который правильный? А сколько байтов Java использует для символа в памяти?

Пожалуйста, дайте мне знать, какой из них правильный и сколько байтов он использует.

7 ответов

Решение

Java использует UTF-16 для внутреннего текстового представления

Представление для String, StringBuilder и т. Д. В Java - UTF-16

https://docs.oracle.com/javase/8/docs/technotes/guides/intl/overview.html

Как текст представлен на платформе Java?

Язык программирования Java основан на наборе символов Unicode, и несколько библиотек реализуют стандарт Unicode. Примитивный тип данных char в языке программирования Java представляет собой 16-разрядное целое число без знака, которое может представлять кодовую точку Unicode в диапазоне от U+0000 до U+FFFF или кодовые единицы UTF-16. Различные типы и классы в платформе Java, которые представляют последовательности символов - char[], реализации java.lang.CharSequence (например, класс String) и реализации java.text.CharacterIterator - являются последовательностями UTF-16.

На уровне JVM, если вы используете -XX:+UseCompressedStrings (который используется по умолчанию для некоторых обновлений Java 6). Фактическое представление в памяти может быть 8-разрядным, ISO-8859-1, но только для строк, которые не нуждаются в кодировке UTF-16.

http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

и поддерживает нестандартную модификацию UTF-8 для сериализации строк.

Сериализованные строки используют UTF-8 по умолчанию.

А сколько байтов Java использует для символа в памяти?

char всегда два байта, если вы игнорируете необходимость заполнения в объекте.

Примечание: кодовая точка (которая допускает символ> 65535) может использовать один или два символа, то есть 2 или 4 байта.

До Java 9 стандартное представление в памяти, используемое в Java String кодовые блоки UTF-16 хранятся в char[], Модифицированный UTF-8 используется в других контекстах; например, в файлах ".class" и в формате сериализации объектов.

Вы можете подтвердить это, посмотрев на исходный код java.lang.String учебный класс.

В Java 6 с обновлением 21 и выше появилась нестандартная опция (-XX:UseCompressedStrings), чтобы включить сжатые строки. Эта функция была удалена в Java 7.

С Java 9 и более поздними String был изменен для использования компактного представления для строк по умолчанию. java командная документация теперь говорит это:

-XX: -CompactStrings

Отключает функцию Compact Strings. По умолчанию эта опция включена. Когда этот параметр включен, строки Java, содержащие только однобайтовые символы, представляются внутри и хранятся как строки, каждая из которых состоит из одного байта, с использованием кодировки ISO-8859-1 / Latin-1. Это уменьшает на 50% объем пространства, необходимого для строк, содержащих только однобайтовые символы. Для строк Java, содержащих как минимум один многобайтовый символ: они представлены и хранятся в виде 2 байтов на символ с использованием кодировки UTF-16. Отключение функции "Компактные строки" заставляет использовать кодировку UTF-16 в качестве внутреннего представления для всех строк Java.

Обратите внимание, что ни "сжатые", ни "компактные" строки не используют / используют кодировку UTF-8.

Смотрите также:

UTF-16.

С http://java.sun.com/javase/technologies/core/basic/intl/faq.jsp:

Как текст представлен на платформе Java?

Язык программирования Java основан на наборе символов Unicode, и несколько библиотек реализуют стандарт Unicode. Примитивный тип данных char в языке программирования Java представляет собой 16-разрядное целое число без знака, которое может представлять кодовую точку Unicode в диапазоне от U+0000 до U+FFFF или кодовые единицы UTF-16. Различные типы и классы в платформе Java, которые представляют последовательности символов - char[], реализации java.lang.CharSequence (например, класс String) и реализации java.text.CharacterIterator - являются последовательностями UTF-16.

Размер char составляет 2 байта.

Поэтому я бы сказал, что Java использует UTF-16 для внутреннего представления String.

По состоянию на 2023 год см. JEP 254: Компактные строки https://openjdk.org/jeps/254.

До JDK 9 это был UTF-16.char value[], обычно 2 байта на символ, 4 байта для азиатского языка (китайский, японский 日本)

Начиная с JDK 9, это UTF-8.byte[]
например, 1 байт для ASCII/латиницы, 2 байта для Áá Àà Ăă Ắắ Ằằ Ẵẵ (буквы с диакритическими знаками), 4 байта для азиатского языка (китайский, японский 日本). По-прежнему можно отключить функцию
компактных строк с помощью-XX:-CompactStrings
см. документацию дляjavaКоманда https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#advanced-runtime-options-for-java

и статья https://howtodoinjava.com/java9/compact-strings/


Класс String ДО Java 9. До Java 9 строковые данные хранились в виде массива символов. Для каждого символа требовалось 16 бит.

      public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
 
    //The value is used for character storage.
  private final char value[];
 
}

Класс String ПОСЛЕ Java 9. Начиная с Java 9, строки теперь внутренне представляются с использованием массива байтов вместе с полем флага для кодирования ссылок.

      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 доступна на 18 международных языках и сопровождается набором символов UNICODE, который содержит все символы, доступные на 18 международных языках, и содержит 65536 символов. И java следует UTF-16, поэтому размер символа в java составляет 2 байта.

Java хранит строки внутри себя как UTF-16 и использует 2 байта для каждого символа.

Другие вопросы по тегам