Java源码___String类(一)

本文深入解析 Java 中 String 类的关键特性,包括其不可变性、序列化能力及如何通过多种构造器创建字符串对象。

java.lang.String 分析摘要:
<1>简介
<2>常量
<3>构造器方法
<4>构造器使用的私有方法

1.简介
 java.lang.String类是我们最常用的类之一,String类本身就是种数据类型,所以查看String的源码是非常重要的。

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

基本属性:final不可继承,也就是说String类不允许覆写、子类继承等操作,字符串是常量,在创建后,字符串的值就不能改变。

实现Serializable序列化接口:能够进行对文件进行序列化和反序列化操作。

实现Comparable比较接口:能够按照一定规则进行排序,这边是按照首字母自然顺序进行比较,如果相等,则依次比较下一位。

实现CharSqequence接口:实现了一些charAt(int index)、toString()等方法。

 
2. 常量
 这里面的都是String类的一些常量。

    /** The value is used for character storage. */
    //字符串的字符仓库
    private final char value[];

    /** Cache the hash code for the string */
    //缓存字符串的hash值,默认为0
    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>
     */
     //String字符串类在序列化协议中是特殊的。其对象序列化规范见上面注释的链接。
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];


 

3.构造器方法
 String的构造器有以下几种:

//<1>注意:因为字符串是不可变的,所以不需要使用该构造方法。
 public String() {
        this.value = "".value;
 }

//<2>初始化新创建的对象,以便它表示与参数相同的字符串序列。
//换句话说,新创建的字符串是参数字符串的副本。
//除非说需要字符串参数的显示拷贝,要不然使用该构造函数是不必要的,因为字符串是不可变的。
public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
}

//<3>用一个字符数组来初始化一个字符串
public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
}

//<4>创建一个新的字符串,它包含了字符数组的子数组中的字符。
//value: 字符数组,用于创建新字符串(包含字符数组的子数组)
//offset:偏移量,也就是数组下标。第一位为0
//count:数量,如果为0,则表示返回一个空字符串。因为复制的数量为0
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;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}

//<5>根据所给的整数数组codePoint的子数组来创建一个字符串
//codePoint:整数数组,其中的整数是Unicode字符代表的数,如65转过为A
//offset:偏移量,值为数组的下标。既:第一个字符为0
//count:偏移的数量。为0时,因为没有偏移,返回空字符串
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;
}

//<6>【该方法已过时】根据byte数组来组成一个字符串的,根据偏移生成子字符串
//ascii[]:byte数组
//hibyte:因为byte是8位数,而转成String是16位。所以前8位则用hibyte来填充
//offset:偏移量,取值为数组坐标,第一位为0
//count:偏移数量,如果为偏移数量为0,则返回空字符串
@Deprecated
public String(byte ascii[], int hibyte, int offset, int count) {
     checkBounds(ascii, offset, count);
     char value[] = new char[count];

     if (hibyte == 0) {
         for (int i = count; i-- > 0;) {
             value[i] = (char)(ascii[i + offset] & 0xff);
         }
     } else {
         hibyte <<= 8;
         for (int i = count; i-- > 0;) {
             value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
         }
     }
     this.value = value;
 }

//<7>【该方法已过时】根据byte数组来来完全拼成一个字符串,调用的是上个构造器的方法
//asccii[]:byte数组
//hibyte:byte是8位,String是16位,前8位则用hibyte来填充
 @Deprecated
 public String(byte ascii[], int hibyte) {
     this(ascii, hibyte, 0, ascii.length);
 }

//<8>使用指定的编码对byte数组进行解码,因为有偏移量和偏移数量,得到是解码后字符串的子串
//bytes[]:byte数组,用于指定编码格式解码
//offset:第一个解码的byte[]的下标
//length:要解码的字节数
//charset:字符集
public String(byte bytes[], int offset, int length, String charsetName)
            throws UnsupportedEncodingException {
   if (charsetName == null)
        throw new NullPointerException("charsetName");
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(charsetName, bytes, offset, length);
}

//<9>根据特定数组和特定字符集来构建一个String对象
public String(byte bytes[], String charsetName)
            throws UnsupportedEncodingException {
   this(bytes, 0, bytes.length, charsetName);
 }
//还有的构造器见下篇

还有的构造器见下篇
 
4. 构造器使用的私有方法

 构造器生成String对象过程中常用的一些方法。

//对构造方法的byte数组进行偏移量以及偏移数量的长度检查
private static void checkBounds(byte[] bytes, int offset, int length) {
   if (length < 0)
       throw new StringIndexOutOfBoundsException(length);
   if (offset < 0)
       throw new StringIndexOutOfBoundsException(offset);
   if (offset > bytes.length - length)
       throw new StringIndexOutOfBoundsException(offset + length);
}

该方法的主要作用是:对数组进行检查,查看是否超过数组长度,如果超过长度则抛异常。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值