字符串常量:

字符串面试题:https://blog.csdn.net/u011541946/article/details/79865160

以下这种情况,则会将 “abc” 这个字符串常量放入字符串常量池,如果之后有其他变量使用相同的字符串,则会指向字符串常量池中的同一个字符串常量

  1. String str = "abc";

而以下这种情况,会创建两个对象。一个是存在于堆中的 String 对象,一个是存在与字符串常量池的 “abc” 字符串常量,堆中 String 对象中存储的是字符串常量池中的拷贝,而不是引用

  1. String str = new String("abc");

String.intern():获取对应的字符串常量超池中的字符串常量

  1. String str1 = "abc";
  2. String str2 = new String("abc");
  3. // false
  4. System.out.println(str1 == str2);
  5. // true
  6. System.out.println(str1.equals(str2));
  7. // true
  8. System.out.println(str1 == str2.intern());
  1. String str1 = "abc";
  2. String str2 = "ab" + "c";
  3. // true
  4. System.out.println(str1 == str2);

使用 “+” 进行字符串对象拼接时,编译器会创建一个空的 StringBuilder 对象,将字符串变量进行 append(),最后再调用 toString() 方法转换成 String 对象,那么这个 String 对象就必然存在于堆中。

  1. String str1 = "abc";
  2. String str2 = "ab";
  3. // String str3 = new StringBuilder().append(str2).append("c").toString()
  4. String str3 = str2 + "c"
  5. // false
  6. System.out.println(str1 == str3);
  7. // true
  8. System.out.println(str1.equals(str3));

编译后的字节码:
image.png


Unicode 和 UTF-8

参考文章:https://www.zhihu.com/question/23374078

Unicode 是字符集

  • 为每个字符都分配一个唯一 ID
  • 在 Java 中, String 底层的 char 数组中,存储的就是这些字符集的 ID

UTF-8 是编码规则

  • 是一套以 8 位为一个编码单位的可变长编码
  1. public static void main(String[] args) {
  2. // -26 -> 230 -> e6
  3. // -75 -> 181 -> b5
  4. // -117 -> 139 -> 8b
  5. // UTF-8: e6 b5 8b
  6. // 1110 0110 1011 0101 1000 1011
  7. String s1 = "测";
  8. byte[] bytes = s1.getBytes(StandardCharsets.UTF_8);
  9. System.out.println("UTF-8:");
  10. for (byte aByte : bytes) {
  11. int unsignedInt = Byte.toUnsignedInt(aByte);
  12. String hexString = Integer.toHexString(unsignedInt);
  13. System.out.printf("%s -> %s -> %s\n", aByte, unsignedInt, hexString);
  14. }
  15. System.out.println();
  16. // 测 -> 6d4b
  17. // Unicode: 6D4B
  18. // 110 1101 0100 1011
  19. char[] chars = s1.toCharArray();
  20. System.out.println("Unicode:");
  21. for (char aChar : chars) {
  22. String hexString = Integer.toHexString(aChar);
  23. System.out.printf("%s -> %s\n", aChar, hexString);
  24. }
  25. }

结果:

UTF-8:
-26 -> 230 -> e6
-75 -> 181 -> b5
-117 -> 139 -> 8b

Unicode:
测 -> 6d4b

注意:我在网上找到的大部分 UTF-8 编码工具,转换的结果都是 Unicode 字符集,而不是真的 UTF-8 编码后的结果。

final 类

String 类为什么设计成不可变的?
1、字符串常量的复用
2、String 对象保存 hashCode,不变的话就不需要考虑去更新
3、安全,String 对象作为方法入参,被很多 JDK 库使用,如果在方法中改变了内容,则容易发生问题
final char[] value

StringBuilder 类

底层存储:

char[] value

append:

  • 如果数组容量不够,会使用复制数组的方法扩容

toString:

  • new String(),会将数组再复制一遍用于创建 string 对象