Согласно документации Java для String.length :
public int length ()
Возвращает длину этой строки.
Длина равна количеству единиц кода Unicode в строке.
Указано:
длина в интерфейсе CharSequence
Возвращает:
длина последовательности
символов, представленных этим объектом.
Но тогда я не понимаю, почему следующая программа HelloUnicode.java выдает разные результаты на разных платформах. Насколько я понимаю, количество единиц кода Unicode должно быть одинаковым, поскольку Java предположительно всегда представляет строки в UTF-16 :
public class HelloWorld {
public static void main(String[] args) {
String myString = "I have a ? in my string";
System.out.println("String: " + myString);
System.out.println("Bytes: " + bytesToHex(myString.getBytes()));
System.out.println("String Length: " + myString.length());
System.out.println("Byte Length: " + myString.getBytes().length);
System.out.println("Substring 9 - 13: " + myString.substring(9, 13));
System.out.println("Substring Bytes: " + bytesToHex(myString.substring(9, 13).getBytes()));
}
// Code from https://stackoverflow.com/a/9855338/4019986
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
Вывод этой программы на моем компьютере с Windows:
String: I have a ? in my string
Bytes: 492068617665206120F09F998220696E206D7920737472696E67
String Length: 26
Byte Length: 26
Substring 9 - 13: ?
Substring Bytes: F09F9982
Вывод на моем компьютере CentOS 7:
String: I have a ? in my string
Bytes: 492068617665206120F09F998220696E206D7920737472696E67
String Length: 24
Byte Length: 26
Substring 9 - 13: ? i
Substring Bytes: F09F99822069
Я запускал оба с Java 1.8. Одинаковая длина байта, другая длина строки. Почему?
UPDATE
Заменив "?" в строке на "\ uD83D \ uDE42", я получу следующие результаты:
Windows
String: I have a ? in my string
Bytes: 4920686176652061203F20696E206D7920737472696E67
String Length: 24
Byte Length: 23
Substring 9 - 13: ? i
Substring Bytes: 3F2069
CentOS:
String: I have a ? in my string
Bytes: 492068617665206120F09F998220696E206D7920737472696E67
String Length: 24
Byte Length: 26
Substring 9 - 13: ? i
Substring Bytes: F09F99822069
Почему «\ uD83D \ uDE42» в конечном итоге кодируется как 0x3F на машине с Windows, мне не понятно ...
Версии Java:
Windows
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
CentOS:
openjdk version "1.8.0_201"
OpenJDK Runtime Environment (build 1.8.0_201-b09)
OpenJDK 64-Bit Server VM (build 25.201-b09, mixed mode)
Обновление 2
Используя .getBytes("utf-8")
, с "?", встроенным в строковый литерал, вот выходные данные.
Windows
String: I have a ? in my string
Bytes: 492068617665206120C3B0C5B8E284A2E2809A20696E206D7920737472696E67
String Length: 26
Byte Length: 32
Substring 9 - 13: ?
Substring Bytes: C3B0C5B8E284A2E2809A
CentOS:
String: I have a ? in my string
Bytes: 492068617665206120F09F998220696E206D7920737472696E67
String Length: 24
Byte Length: 26
Substring 9 - 13: ? i
Substring Bytes: F09F99822069
Так что да, похоже, разница в кодировке системы. Но тогда это означает, что строковые литералы кодируются по-разному на разных платформах? Похоже, это может быть проблематично в определенных ситуациях.
Также ... откуда берется последовательность байтов C3B0C5B8E284A2E2809A
для представления смайлика в Windows? Это не имеет смысла для меня.
Для полноты, используя .getBytes("utf-16")
, с "?", встроенным в строковый литерал, вот выходные данные.
Windows
String: I have a ? in my string
Bytes: FEFF00490020006800610076006500200061002000F001782122201A00200069006E0020006D007900200073007400720069006E0067
String Length: 26
Byte Length: 54
Substring 9 - 13: ?
Substring Bytes: FEFF00F001782122201A
CentOS:
String: I have a ? in my string
Bytes: FEFF004900200068006100760065002000610020D83DDE4200200069006E0020006D007900200073007400720069006E0067
String Length: 24
Byte Length: 50
Substring 9 - 13: ? i
Substring Bytes: FEFFD83DDE4200200069