我有一个测试字符串:
String test = "oiwfoilfhlshflkshdlkfhsdlfhlskdhfslkhvslkvhvkjdhfkljshvdfkjhvdsköljhvskljdfhvblskjbkvljslkhjjssdlkhdsflksjflkjdlfjslkjljlfjslfjldfjjhvbksdjhbvslkdfjhbvslkjvhbslkvbjbn";
在调试过程中,我注意到以下内容。当我打印出长度时:
System.out.println("Test length() : " + test.length());
返回
测试长度():166
调试时,我可以将333读取为 count 作为测试变量。
计数代表什么?
答案 0 :(得分:4)
字符串实现包含一个字符数组-值。因此,某些实现中的 count 字段用于计算数组的声明大小。
您可能会注意到,提供的 count 值两次不同于给定的字符串长度-这似乎暗示了按照1 Unicode(UTF-16)的ASCII / UTF-8 / UTF-16差异符号在String实例中由2个字节表示。
一个例子:
String str = "f";
str.length(); // 1
str.getBytes().length; // 1
但是
String str = "ў";
str.length(); // 1
str.getBytes().length; // 2
另请参阅:
您正在使用什么JDK?可能会使您更清楚地了解计数。
答案 1 :(得分:3)
在询问here与Java有关的问题时,请务必提及,因为存在一些主要差异。
android ART运行时通过将通常的两字节Java字符压缩为单字节ASCII字符串来优化java.lang.String
。您可以在android的源代码中看到它:
public int length() {
// BEGIN Android-changed: Get length from count field rather than value array (see above).
// return value.length;
final boolean STRING_COMPRESSION_ENABLED = true;
if (STRING_COMPRESSION_ENABLED) {
// For the compression purposes (save the characters as 8-bit if all characters
// are ASCII), the least significant bit of "count" is used as the compression flag.
return (count >>> 1);
} else {
return count;
}
}
在java.lang.String
中指定了字符串压缩:
// String Compression
static constexpr bool kUseStringCompression = true;
enum class StringCompressionFlag : uint32_t {
kCompressed = 0u,
kUncompressed = 1u
};
此标志为native code as,其值为count
:
static int32_t GetFlaggedCount(int32_t length, bool compressible) {
return kUseStringCompression
? static_cast<int32_t>((static_cast<uint32_t>(length) << 1) |
(static_cast<uint32_t>(compressible
? StringCompressionFlag::kCompressed
: StringCompressionFlag::kUncompressed)))
: length;
}
但是,从常量池加载字符串时,不执行字符串压缩。因此,您得到的原始字符数加倍为1(333 = 166 * 2 +1)。额外的1是“未压缩”标志。