JDK源码阅读-基础类-String

3 篇文章 0 订阅

一、String概况

1.1 String概述

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
  • 被pulic修饰的不可被继承的类

1.2 UML类图

«interface»
CharSequence
#int length()
#char charAt(int index)
#CharSequence subSequence(int start, int end)
+String toString()
+default IntStream chars()
+IntStream codePoints()
String
«interface»
Serializable
«interface»
Comparable
+int compareTo(T o)
  • 实现了Comparable接口,可用于比较String对象大小;
  • 实现了Serializable接口,所以String可以实现序列化。
  • 实现了CharSequence接口:
    • CharSequence接口是一个描述字符串结构的接口;
    • 定义了一些对字符串的常用操作;

参考资料:

二、String属性分析

//存放String左右字符的字符数组
private final char value[];
//存放String的hash码值
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
       new ObjectStreamField[0];

分析:

  • 存放String所有字符串的value数组被final修饰,是不可变常量–>String一经实例化即不可在变
  • String的hash值是可变的,根据String实例的不同,其hash地址也不同;

三、String方法分析

3.1 构造方法

public String();
public String(String original);
public String(char value[]);
public String(char value[], int offset, int count);
public String(int[] codePoints, int offset, int count);
public String(byte ascii[], int hibyte, int offset, int count);
public String(byte ascii[], int hibyte);
public String(byte bytes[], int offset, int length, String charsetName)
            throws UnsupportedEncodingException;
public String(byte bytes[], int offset, int length, Charset charset);
public String(byte bytes[], String charsetName) throws UnsupportedEncodingException;
public String(byte bytes[], Charset charset);
public String(byte bytes[], int offset, int length);
public String(byte bytes[]);
public String(StringBuffer buffer);
public String(StringBuilder builder);
String(char[] value, boolean share);

String提供多种方式的构造方法,具备不同情况下构造String对象的能力;

3.1.1 String() & String(String original)

public String() {
	//将空字符串的值赋值为String的value属性
 	this.value = "".value;
}

public String(String original) {
	//将参数String对象的value和hash赋值给构造的String对象
    this.value = original.value;
    this.hash = original.hash;
}

如代码所示:

  • 在Stirng()中,给String实例赋值为空;
  • 在String(String s)构造方法中,将s实例的value和hash赋值给新构造的String实例;
    • 由于数组通过“=”赋值是地址引用传递(value指向同一个数组地址),hash是int类型,属于值传递(同一个hash地址),故新构造的String实例与参数String s实例严格来说是同一个对象;

3.1.2 char[] 转 String

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

public String(char value[], int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    //count小于0报错,等于0返回空字符串
    if (count <= 0) {
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= value.length) {
            this.value = "".value;
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    //其实偏移量 + count要小于等于数组长度,否则报错
    if (offset > value.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}
  • 字符数组转字符串,底层代码逻辑都是数组新建-字符复制-赋值;
    • 通过System.arraycopy(Object src, int srcPos,Object dest, int destPos, int length)实现,该方法是被native修饰的本地方法;
  • 在String(char value[], int offset, int count)中,对偏移量和count是有一定要求的:
    • offset代表冲字符数组value的那个字符开始复制:起始字符偏移量/索引;
    • count代表从字符数value中复制多少个字符:字符数量;
    • offset和count都不能小于0;
    • offset + count不能大于value的字符总个数;

3.1.3 int[]转String

public String(int[] codePoints, int offset, int count) {
	//参数有效性校验
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count <= 0) {
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= codePoints.length) {
            this.value = "".value;
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > codePoints.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }

	//结束索引
    final int end = offset + count;

    // Pass 1: Compute precise size of char[]
    //字符素组容量计算
    int n = count;
    for (int i = offset; i < end; i++) {
        int c = codePoints[i];
        //校验int数组中的元素是否在Bmp范围内,是的话一个字符就可以表示
        if (Character.isBmpCodePoint(c))
            continue;
        //判断int数组中的元素在超过bmp范围后,是否在unicode的合理取值范围内
        //在合理取值范围内,由于超过了bmp,需要2个字符才能表示一个int数组元素,数组容量+1
        //如果没在合理范围内,抛异常
        else if (Character.isValidCodePoint(c))
            n++;
        else throw new IllegalArgumentException(Integer.toString(c));
    }

    // Pass 2: Allocate and fill in char[]:新建字符数组
    final char[] v = new char[n];

    for (int i = offset, j = 0; i < end; i++, j++) {
        int c = codePoints[i];
        //int数组元素在bmp范围内,直接数组转字符并存放到字符数组中
        if (Character.isBmpCodePoint(c))
            v[j] = (char)c;
        else//int数组元素在bmp到合理范围内,一个int数组元素用2个字符表示;
            Character.toSurrogates(c, v, j++);
    }

    this.value = v;
}
  • bmp:unicode中 0x0000-0xffff 被称作BMP (Basic Multilingual Plane),char只能表示BMP;
  • unicode的合理取值范围:0x0000-0x10ffff,一共21位,二进制
    0000 0000 0000 0001 0000 1111 1111 1111 1111;

参考资料:String: public String(int[] codePoints,int offset,int count) 由int数组转化的构造方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值