Каково внутреннее представление 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 для сериализации строк.
Другой это:
и это говорит:
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 байта для каждого символа.