String源码解析

好久没有看源码了,这次看看String源码学习知识

继承

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

  • 用final来修饰表示string是个最终类,不可被继承
  • java.io.Serializable, Comparable, CharSequence 实现了这三个接口,依次是序列化,比较,和字符序列

基本属性

//字符串底层是字符数组
private final char value[];
//哈希值
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;
//用于忽略大小写得比较两个字符串。
private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];
  • 字符串的底层是字符数组

构造方法

    //默认构造为空字符串
    public String() {
        this.value = "".value;
    }
    //将字符串直接赋给字符串
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    //如果给定的是字符串数组的话,取该数组前 value.length位的字符
      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);
        }
        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);
        }
        //上面是一系列判断
       //该方法是生成一个新的char【】然后赋给value数组,且如果offset+count超过了给定的value【】数组的大小,那么范围取值到value数组的最后一位
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
   public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }
   public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }
  • string的构造函数本质上都是在调用Arrays.copyOf()这个本地方法,创建一个新的字符串数组来返回然后赋值给value数组

一些基本的方法

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

  • 因为字符串的底层是数组,这里就是调用了数组的一些方法

一些字符串的比较方法

      //区分大小的比较方法
    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            //这里考虑大小写,所以如果不一样直接返回对位字符的差值
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

    //不区分大小的比较方法
    public int compareToIgnoreCase(String str) {
        return CASE_INSENSITIVE_ORDER.compare(this, str);
    }
     //
    public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();
    private static class CaseInsensitiveComparator
            implements Comparator<String>, java.io.Serializable {
        // use serialVersionUID from JDK 1.2.2 for interoperability
        private static final long serialVersionUID = 8575799808933029326L;
        //返回的是整形,二者的插值
        public int compare(String s1, String s2) {
            int n1 = s1.length();
            int n2 = s2.length();
            int min = Math.min(n1, n2);
            for (int i = 0; i < min; i++) {
                char c1 = s1.charAt(i);
                char c2 = s2.charAt(i);
                if (c1 != c2) {
                     //统一大写比较
                    c1 = Character.toUpperCase(c1);
                    c2 = Character.toUpperCase(c2);
                    if (c1 != c2) {
                         //统一小写比较
                        c1 = Character.toLowerCase(c1);
                        c2 = Character.toLowerCase(c2);
                         //这里没有结束,返回二者对位字符的差值的差值
                        if (c1 != c2) {
                            // No overflow because of numeric promotion
                            return c1 - c2;
                        }
                    }
                }
            }
            //如果前面相等返回长度的差值
            return n1 - n2;
        }

    public static void main(String[] args) {
        char[] chars={'5','5','b'};
        String s=new String(chars);
        int i = s.compareToIgnoreCase("55a");
        //return 1;
        System.out.println(i);
    }

    public static void main(String[] args) {
        char[] chars={'5','a','b'};
        String s=new String(chars);
        int i = s.compareToIgnoreCase("5abcsda"); 
        //return -4;
        System.out.println(i);
    }
  • 不考虑大小写的方法的比较是将对应字符统一大小写后进行比较
  • 大小的比较是从头开始比,如果碰到了一个不相同的就结束判断得出大小

判断相不相等

  //只需要内容相等就相等
 public boolean equals(Object anObject) {
        //如果双方的引用相同,那么二者相等
        if (this == anObject) {
            return true;
        }
        //如果没有继承相同的接口
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
             //判断长度相等后,挨个字符进行比较
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    //这里会调用 regionMatches 统一大小写后进行判断
      public boolean equalsIgnoreCase(String anotherString) {
        return (this == anotherString) ? true
                : (anotherString != null)
                && (anotherString.value.length == value.length)
                && regionMatches(true, 0, anotherString, 0, value.length);
    }

  • 比较大小和相同的理念都类似就是挨个字符进行比较,如果有不同的就退出比较。

判断字符第一次出现的位置

//fromIndex起始位置,默认为0
//ch 需要寻找的字符
public int indexOf(int ch, int fromIndex) {
        //一些范围判断
        final int max = value.length;
        if (fromIndex < 0) {
            fromIndex = 0;
        } else if (fromIndex >= max) {
            // Note: fromIndex might be near -1>>>1.
            return -1;
        }
        //需要判断是否存在的字符要在Unicode编码里面
        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid code point))
            //定义为final,就算value改变了引用也不会影响到这个字符串
            final char[] value = this.value;
           //如果找到返回下标,没找到返回-1;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
            return indexOfSupplementary(ch, fromIndex);
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值