java.lang.String:length()vs. count?

时间:2018-12-12 14:01:53

标签: java android-studio

我有一个测试字符串:

String test = "oiwfoilfhlshflkshdlkfhsdlfhlskdhfslkhvslkvhvkjdhfkljshvdfkjhvdsköljhvskljdfhvblskjbkvljslkhjjssdlkhdsflksjflkjdlfjslkjljlfjslfjldfjjhvbksdjhbvslkdfjhbvslkjvhbslkvbjbn";

在调试过程中,我注意到以下内容。当我打印出长度时:

System.out.println("Test length() : " + test.length());

返回

  

测试长度():166

调试时,我可以将333读取为 count 作为测试变量。

enter image description here

计数代表什么?

2 个答案:

答案 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。您可以在的源代码中看到它:

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是“未压缩”标志。