源码现状

阅读源码可以发现,String被final修饰,其value变量也被final修饰,这是2件事;
首先,String类被final修饰,类不可以被继承。规避了有人想尝试通过继承重写来破坏String内部的数据;
其次,内部成员变量char value[] 被final修饰,value引用地址不可变;

原因分析

安全

1.使用安全,String是最常用的对象,不可变规避了直接在堆中直接改变对象内容,除非主动修改引用地址,否则我们将String传递进任何方法中,他都不会改变,防止一不小心就在其他函数内被更改了;
2.线程安全,并发使用String时,不需要再去考虑他的线程安全问题;

性能

1.字符串缓冲池,使用享元模式,减少String对象的产生,而享元模式的弊端就是对象的内部状态不可变;
2.hash算法,由于String初始化就不可变,所以一个String的hashcode是固定的不变的,可以只计算一次,并且String是最适合作为hashMap中的Key;

个人思考

为什么String类被final修饰,要从字符串享元开始说起

  • 假设定义String都产生新对象,那么初始化多个"ABC"时,在内存中就存在多个"ABC"的字符串对象占据空间;
  • 这时考虑节约空间,就应先创建内存空间来存放这个"ABC",再让所有需要使用这个字符串的对象直接指向这个地址;
  • 这时就需要避免内存中"ABC"的值不能被其他人改变(也就是String的value),故value变量是final修饰的(若不是final,则指针指向内存空间中的值就会被改变);

承上,就算value被final修饰,也可能被子类通过覆盖方法来修改内存中的值,因此String类也是final修饰,从而做到了不可变,即String一旦定义,就不会改变;

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

  /** Cache the hash code for the string */
  private int hash; // Default to 0

  /** use serialVersionUID from JDK 1.0.2 for interoperability */
  private static final long serialVersionUID = -6849794470754667710L;

  /**
   * Class String is special cased within the Serialization Stream Protocol.
   *
   * A String instance is written into an ObjectOutputStream according to
   * <a href="{@docRoot}/../platform/serialization/spec/output.html">
   * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
   */
  private static final ObjectStreamField[] serialPersistentFields =
      new ObjectStreamField[0];

  /**
   * Initializes a newly created {@code String} object so that it represents
   * an empty character sequence.  Note that use of this constructor is
   * unnecessary since Strings are immutable.
   */
  public String() {
      this.value = "".value;
  }

  /**
   * Initializes a newly created {@code String} object so that it represents
   * the same sequence of characters as the argument; in other words, the
   * newly created string is a copy of the argument string. Unless an
   * explicit copy of {@code original} is needed, use of this constructor is
   * unnecessary since Strings are immutable.
   *
   * @param  original
   *         A {@code String}
   */
  public String(String original) {
      this.value = original.value;
      this.hash = original.hash;
  }
}

老污的猫
30 声望5 粉丝