三、String源码解读(一)

一、String类的继承关系

String类的继承关系如图所示:
在这里插入图片描述
String主要实现了Serializable、Comparable、CharSequence这三个接口。

  • Serializable接口:Serializable接口是实现的序列化,实现这个接口就是表示这个类是可以被序列化的。
  • Comparable接口:Comparable接口主要是实现对象比较的。Comparable接口的方法就一个就是compareTo。
	/**
 	 * Compares this object with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     */
     public int compareTo(T o);

compareTo方法的注释的意思是这个对象和一个指定的对象进行排序。返回一个负整数、0、和正整数。负整数是这个对象小于指定的对象,0是表示这个对象等于指定的对象,正数表示的是这个对象大于指定的对象。

  • CharSequence接口:CharSequence接口是char的可读序列。CharSequence的主要方法如下:
    在这里插入图片描述

二、String类中的字段

String中主要的字段有char数组value、int型的hash、long类型的serialVersionUID、ObjectStreamField数组的serialPersistentFields和Comparator的CASE_INSENSITIVE_ORDER
在这里插入图片描述

  • value:这个是用来进行字符存储的。
  • hash:这个是用来表示字符串的hash码。
  • serialVersionUID:这个是用来表示String类的序列化的ID(从jdk1.2开始)
  • CASE_INSENSITIVE_ORDER:这个是一个String的比较器。

三、String类中的方法

3.1 构造方法

String类的构造方法主要有下面几种
在这里插入图片描述
主要相关的可以分为参数为无参类型构造、String类型构造、char数组类型构造、int数组类型构造、byte数组类型构造、StringBuffer和StringBuilder类型构造。

  • 参数无参构造方法:无参数构造方法主要就是初始化了一个空的字符数组给成员变量value字符数组。
    public String() {
        this.value = "".value;
    }
  • 参数String类型的构造方法:方法参数为String类型就是将String对象中的value数组和hash码赋值给新建的String对象。因此这个这个方法会新建一个String对象
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
  • 参数char数组类型的构造方法:
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
  • 参数int数组类型的构造方法:方法参数为int数组类型的就是int数组中的每个int整转成char类型,然后char数组赋值给String对象中的value字符数组
    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];
            if (Character.isBmpCodePoint(c))
                continue;
            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];
            if (Character.isBmpCodePoint(c))
                v[j] = (char)c;
            else
                Character.toSurrogates(c, v, j++);
        }

        this.value = v;
    }
  • 参数byte数组类型的构造方法:方法参数是byte数组类型就是利用StringCoding解析这个byte数组,然后将解析出来的char数组赋值给String类的value变量。
    public String(byte bytes[], int offset, int length) {
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(bytes, offset, length);
    }
  • 参数StringBuffer类型的构造方法:方法参数是StringBuffer类型就是将方法参数StringBuffer对象中的属性字符数组value取出来拷贝给String类型的value变量。
    public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }
  • 参数StringBuilder类型的构造方法:方法参数是StringBuilder类型类似参数是StringBuffer类型的参数。
    public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }
  • 还有一种就是字符串赋值的方式,这种采用用的的是字符串缓冲池。这个在编译期检测到了字符串的存在就会去常量池中查找有没有引用指向堆中的String对象,并且该对象的字符序列等于java(下面代码示例),如果有,则将变量的指向堆中的String对象,如果没有就会创建一个String对象,并且将引用放到常量池中,并且将变的引用指向堆内新建的String对象。
        String s = "java";
        String s1 = "java";
        String s2 = "java";
        String s3 = new String("hello");
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);

执行结果

true
false

在编译的时候s1没有从常量池找到java对象的引用,所以在堆内创建了java字符串对象,而s2则在常量池中找到了java字符串对象的引用,所以直接将java字符串引用给了s2,因此s2和s1是相等的,s3则是在堆内重新创建了一个对象,和s1的引用完全不一样,所以s1和s3不相等。

3.2 常用方法

String类中常用的方法有很多,下面只是我在工作常用的一些方法

3.2.1 charAt

charAt的主要作用就是返回指定下表的字符。 charAt的方法参数是一个int类型的下标,返回值是一char字符。主要代码如下

    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

代码就是直接返回字符数组value的指定的下标的字符。

3.2.2 getChars

getChar的主要作用是对value的字符数组进行拷贝操作。getChar的方法参数是数据源的起始位置srcBegin,数据源的结束为止srcEnd,需要赋值的字符数组dst[],需要赋值的字符数组的起始位置dstBegin。其中一方法如下

    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

代码主要实现就是利用System.arraycopy将String属性的value字符数组当成数据源,然后将value拷贝指定长度的数据到目标字符数组的指定位置。像下面代码

    public static void getCharsString(String s) {
        char[] chars = new char[1024];

        s.getChars(1, 3, chars, 3);
        for (int i = 3; i < 5; i++) {
            System.out.println(chars[i]);
        }
    }

传入参数java,输出结果是

a
v

拷贝的就是从java的第1位开始,拷贝3-1=2个长度就是a和v。

3.2.3 getBytes

getBytes的主要作用是将字符串转成字节数组。方法参数是一个字符集charsetName。

    public byte[] getBytes(String charsetName)
            throws UnsupportedEncodingException {
        if (charsetName == null) throw new NullPointerException();
        return StringCoding.encode(charsetName, value, 0, value.length);
    }

主要是利用了StringCoding将String对象属性的value字符数组解析成一个字节数组。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Oak_Fei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值