String源码分析 成员变量与构造器

题记:

    String作为我们工作中最常用的类之一,一直没有完整的看过其底层的源码

类:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence { }

1.String类的修饰符有一个final所以它是不能被继承的

2.实现接口

    java.io.Serializable这是一个序列化接口里面没有任何方法和域,仅用于标识序列化

   Comparable<String> 标识这个接口,用于对两个实例化对象比较大小

   CharSequence 这个接口是一个只读的字符序列。包括length(), charAt(int index), subSequence(int start, int end)这几个API接口,值得一提的是,StringBuffer和StringBuild也是实现了改接口。

 

一.成员变量

 1.char value[]

 private final char value[];

    是用于存储String的内容的 每个字符串实际上都是一个char[]数组 例如String str = "ABC",实际存储为char[] str = {'A','B','C'}

  2.int hash

private int hash;

     这里的hash是String实例化的hashcode的一个缓存,使用私有变量缓存了hash值 使用了利用空间来换取时间

  3.long serialVersionUID

private static final long serialVersionUID = -6849794470754667710L;

     用于版本判定

  4.OjectStreamField[] serialPersistentFields 

private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];

    需要序列化的部分

 

二.构造器

      JDK1.8中String类一共由16个构造器其中 有两个带有@Deprecated(不推荐使用) 一个私有构造器

  1.无参构造器 

 public String() { this.value = "".value; }

       无参构造器直接将""的value赋值给当前类的value. value的length则为0,当前是一个""(空字符串)而不是null hashCode为0

  2.传入参数为String对象

 public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
 }

        构造器直接对其进行取值

  3.传入参数为char[]

public String(char value[]) {
       this.value = Arrays.copyOf(value, value.length);
}

        构造器==>>Arrays.copyOf()方法==>>System.arraycopy();进行了拷贝

public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
}

4.传入char[]数组,偏移量(下标)和长度

public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
}

      通过offset(偏移量)和count(长度)来查找子串并赋值给this.value然后调用Arrays.copyOfRange方法进行深拷贝

 char[] chars = {'A','B','C'};
 String str = new String(chars,1,2);  //BC

      注意: offset不能填入负数也不能填入超出数组长度的数值 count也不能填入负数也不能填入超出剩余长度的值

      否则会抛出 java.lang.StringIndexOutOfBoundsException: String index out of range 异常

5.传入char[]数组,偏移量(下标)和长度

 public String(char value[], int offset, int count){}

  6.  传入int[]数组最后获得的是相对应的Unicode的字符

public String(int[] codePoints, int offset, int count){}
 int[] arr = {97,99,98};
 String str = new String(arr,0,arr.length);  //abc

7.弃用的方法

@Deprecated
public String(byte ascii[], int hibyte, int offset, int count){}

8.弃用的方法

@Deprecated
public String(byte ascii[], int hibyte) {}

9. 传入byte[]数组,偏移量(下标)和长度, charsetName编码格式 生成新的字符串

public String(byte bytes[], int offset, int length, String charsetName)
    throws UnsupportedEncodingException{}

10.传入byte[]数组,偏移量(下标)和长度,charset字符集

public String(byte bytes[], int offset, int length, Charset charset)
  Charset charset = Charset.forName("UTF-8");                     //指定字符集
  String str = new String(bytes,0,3,charset);     

11.传入byte[]数组,charsetName编码格式 生成新的字符串

public String(byte bytes[], String charsetName)
         throws UnsupportedEncodingException {}

12.通过使用平台默认的字符集构造一个新的String 传入 byte[]数组,偏移量(下标)和长度

public String(byte bytes[], int offset, int length) {}

13.传入byte[]数组 调用的是12的构造方法

public String(byte bytes[]) { this(bytes, 0, bytes.length); }

14.15. 传入可变字符串对象 

public String(StringBuffer buffer){    //StringBuffer 
    synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}

public String(StringBuilder builder){  //StringBuilder 
    this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

      因为StringBuffer 是线程安全的 所以会添加锁,而StringBuilder是线程不安全的所以不会进行添加锁

最终的实现都是通过Arrays.copyOf()    他们的toString方法都调用了String的方法

@Override
public synchronized String toString() {    //StringBuffer的toString方法
    if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
    }
    return new String(toStringCache, true);
}


@Override
public String toString() {                    //StringBuilder的toString方法
   // Create a copy, don't share the array
   return new String(value, 0, count);
}

16.这是一个保护类型的构造方法.我们不能调用这个方法

String(char[] value, boolean share) {
   // assert share : "unshared not supported";
    this.value = value;
}

          该方法相比传入为char[]的构造方法多了一个share(共享)的boolean参数,这个参数并没有实际作用,

   只是为了和其他构造器进行区分.当String类内部调用该构造器时    

        (1) 直接进行赋值而不是使用Arrays.copyOf()方法效率会提高

        (2) 共享字符串数组方式可以节省内存

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值