当前位置:网站首页>今天说说String相关知识点

今天说说String相关知识点

2022-06-25 22:06:00 程の编程日记

String

如何实现以及特性

String类被final修饰,所以String不可被继承,Integer等等的包装类都不可以被继承。

jdk1.8中,String底层使用final修饰的char数组来存储字符串

private final char value[];

jdk1.9之后,底层使用final修饰的byte数组来存储字符串

private final byte[] value;

使用final关键字修饰,说明这个value数组初始化之后就不能引用其他数组,String内部也没有改变value数组的方法,因此String不可变。

不可变的好处

  1. 缓存哈希值

    例如HashMap中使用String作为key,因为不可变,所以哈希值只需要一次计算,String类中也有相关代码。

    /** Cache the hash code for the string */
        private int hash; // Default to 0
    
  2. String Pool(字符串常量池)的需要

    当一个String对象被创建过了,就会是从String Pool取得的引用,如果String可变的话,String Pool就无法使用了。

  3. 线程安全

String,StringBuffer,StringBuilder

  1. 可变性

    • String不可变

    • StringBuffer和StringBuilder可变

      这俩为啥可变,因为都继承自一个AbstractStringBuilder,而这个类中提供了构造方法,基于一个容量可变的数组

      /** * Creates an AbstractStringBuilder of the specified capacity. */
      AbstractStringBuilder(int capacity) {
              
          value = new char[capacity];
      }
      

      两个小弟都是调用父类构造方法,传入一个默认容量16来作为初始容量

      // StringBuilder
      public StringBuilder(String str) {
              
              super(str.length() + 16);
              append(str);
          }
      // StringBuffer
      public StringBuffer(String str) {
              
              super(str.length() + 16);
              append(str);
          }
      

      append方法,容量可控制

      public AbstractStringBuilder append(String str) {
              
              if (str == null)
                  return appendNull();
              int len = str.length();
              ensureCapacityInternal(count + len);
              str.getChars(0, len, value, count);
              count += len;
              return this;
          }
      private void ensureCapacityInternal(int minimumCapacity) {
              
              // overflow-conscious code
              if (minimumCapacity - value.length > 0) {
              
                  value = Arrays.copyOf(value,
                          newCapacity(minimumCapacity));
              }
          }
      
  2. 线程安全

    • String 线程安全

    • StringBuffer线程安全,内部方法加锁,比如append

      @Override
      public synchronized StringBuffer append(String str) {
              
          toStringCache = null;
          super.append(str);
          return this;
      }
      
    • StringBuilder 线程不安全,因为没有加锁,性能要比StringBuffer稍微好一点

  3. 使用场景

    • String 操作少量数据
    • StringBuffer 多线程,操作大量数据
    • StringBuilder 单线程,操作大量数据

StringPool

intern方法

可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。

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

在这里插入图片描述

举例说明:

String a = new String("aaa");
String b = new String("aaa");
System.out.println(a == b);     // false
// 使用intern取得字符串引用
String c = a.intern();
String d = a.intern();
System.out.println(c == d);     // true
// 如果是下面这种创建字符串,会直接放入字符串池中
String e = "aa";
String f = "aa";
System.out.println(e == f);     // true

通俗来讲,intern()方法就是获取字符串引用,没有的话就放入池子,返回引用,有的话就直接返回引用。

所以我们进行字符串赋值的时候可以使用intern()来通过引用来节省空间。

原网站

版权声明
本文为[程の编程日记]所创,转载请带上原文链接,感谢
https://blog.csdn.net/hsunnyc/article/details/107605371