【Java基础】String

概述

在Java8中,String内部使用char数组存储数据。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
}

在Java9之后,String类的实现改用byte数组存储字符串,同时使用coder来标识使用了哪种编码。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final byte[] value;

    /** The identifier of the encoding used to encode the bytes in {@code value}. */
    private final byte coder;
}

value数组被声明为final,并且String没有提供可以更改value数组的方法,所以String不可以变。

String 中的 +

String s = "123" + "456"; 
等价于 
String s = "123456";
String s1 = "123";
String s2 = "456";

String s3 = s1 + s2;
等价于
String  s3 = new StringBuilder(s1).append(s2).toString();
final String s1 = "123";
final String s2 = "456";

String s3 = s1 + s2;
等价于
String  s3 = "123456";

String、StringBuffer、StringBuilder

  1. 可变性
  • String 不可变
  • StringBuffer和StringBuilder可变
  1. 线程安全
  • String不可变,因此是线程安全的
  • StringBuilder不是线程安全的
  • StringBuffer是线程安全的(每个方法都用synchronized加锁)

字符串常量池(String Pool)

字符串常量池保存着所有字符串字面量,也可以通过String的intern()方法在运行过程中将字符串添加到String Pool中。

当一个字符串调用intern()方法时,如果String Pool中已经存在一个字符串和该字符串值相等(equal()),那么就会返回String Pool中字符串中的引用;否则,就会在String Pool中添加一个新的字符串,并返回这个新字符串的引用。

String s1 = "123"; // 指向常量池的引用
String s2 = new String("123"); // 指向堆上的引用
String s3 = s2.intern();
System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // true

JDK1.6中,常量池在永久代,intern方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中这个字符串实例的引用。
JDK1.7中,常量池移到Java堆中,intern方法不会再复制实例,而是直接存储堆中的引用

new String(“123”)

使用这种方式一共创建两个字符串对象(前提是String Pool中还没有“123”字符串对象)

  • 常量池中
  • 堆中
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

从String的构造方法中可以看到,value数组是共享的,hash也是共享的。

参考

猜你喜欢

转载自blog.csdn.net/qq_21687635/article/details/89552234