java.lang.String (JDK 1.8)

研究一个类之前我们来说说类的构成:
              一个类主要分为几个部分:分别是类的定义(类的继承,接口的实现),全局变量方法,属性,内部类等.

 第一点: 实现的接口

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

 Sting 是一个由final 修饰的常量类,在java中由final修饰的常量类是不可以任何类被继承的,同时一个String对象被创建, 包含在这个对象中的字符序列是不可改变的,实现Serializable 序列化接口,Comparable用于对两个实例化对象比较大小,CharSequence一个只读的字符序列。

//序列化接口
public interface Serializable {
}

//比较两个实例化对象大小的接口
public interface Comparable<T> {

    public int compareTo(T o);
}
//一个只读的字符序列
public interface CharSequence {

    int length();

   
    char charAt(int index);

   
    CharSequence subSequence(int start, int end);
    
    public String toString();

    public default IntStream chars() {
        class CharIterator implements PrimitiveIterator.OfInt {
            int cur = 0;

            public boolean hasNext() {
                return cur < length();
            }

            public int nextInt() {
                if (hasNext()) {
                    return charAt(cur++);
                } else {
                    throw new NoSuchElementException();
                }
            }

            @Override
            public void forEachRemaining(IntConsumer block) {
                for (; cur < length(); cur++) {
                    block.accept(charAt(cur));
                }
            }
        }

        return StreamSupport.intStream(() ->
                Spliterators.spliterator(
                        new CharIterator(),
                        length(),
                        Spliterator.ORDERED),
                Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.ORDERED,
                false);
    }

    public default IntStream codePoints() {
        class CodePointIterator implements PrimitiveIterator.OfInt {
            int cur = 0;

            @Override
            public void forEachRemaining(IntConsumer block) {
                final int length = length();
                int i = cur;
                try {
                    while (i < length) {
                        char c1 = charAt(i++);
                        if (!Character.isHighSurrogate(c1) || i >= length) {
                            block.accept(c1);
                        } else {
                            char c2 = charAt(i);
                            if (Character.isLowSurrogate(c2)) {
                                i++;
                                block.accept(Character.toCodePoint(c1, c2));
                            } else {
                                block.accept(c1);
                            }
                        }
                    }
                } finally {
                    cur = i;
                }
            }

            public boolean hasNext() {
                return cur < length();
            }

            public int nextInt() {
                final int length = length();

                if (cur >= length) {
                    throw new NoSuchElementException();
                }
                char c1 = charAt(cur++);
                if (Character.isHighSurrogate(c1) && cur < length) {
                    char c2 = charAt(cur);
                    if (Character.isLowSurrogate(c2)) {
                        cur++;
                        return Character.toCodePoint(c1, c2);
                    }
                }
                return c1;
            }
        }

        return StreamSupport.intStream(() ->
                Spliterators.spliteratorUnknownSize(
                        new CodePointIterator(),
                        Spliterator.ORDERED),
                Spliterator.ORDERED,
                false);
    }
}

 第二点:属性

    /** The value is used for character storage. */ 用来存储字符窜
    private final char value[];

    /** Cache the hash code for the string */缓存字符串的哈希码
    private int hash; // Default to 0

 可以看到,value[]是存储String的内容的,即当使用String str = "abc";的时候,本质上,"abc"是存储在一个char类型的数组中的。   

 而hash是String实例化的hashcode的一个缓存。因为String经常被用于比较,比如在HashMap中。如果每次进行比较都重新计算hashcode的值的话,那无疑是比较麻烦的,而保存一个hashcode的缓存无疑能优化这样的操作。

第三点:构造方法

 

第四点:常用的方法

  

     //返回字符窜的长度  
public int length() {
return value.length; } //判断字符窜是否为空 public boolean isEmpty() { return value.length == 0; } //返回指定索引下的字符(一个字符窜实际上是由一个字符数组组成) public char charAt(int index) {
//索引越界抛出异常
if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; }

 Comparable 接口的方法,比较两个字符窜对象的大小

//这个按字母顺序比较两个字符串,是基于字符串中每个字符的 Unicode 值。当两个字符串某个位置的字符不同时,返回的是这一位置的字符 Unicode 值之差,当两个字符串都相同时,返回两个字符串长度之差
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; }

 concat 主要拼接字符窜操作,如果拼接的字符窜为空,返回当前当前子字符窜,不为空则在尾部拼接新的字符窜(长度为原字符串和要拼接的字符串之和)

public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

int indexOf(String str) :返回第一次出现的指定子字符串在此字符串中的索引。

public int indexOf(String str) {
        return indexOf(str, 0);
    }

 int indexOf(String str, int startIndex):从指定的索引处开始,返回第一次出现的指定子字符串在此字符串中的索引。

public int indexOf(String str, int fromIndex) {
        return indexOf(value, 0, value.length,
                str.value, 0, str.value.length, fromIndex);
    }

 int lastIndexOf(String str) :返回在此字符串中最右边出现的指定子字符串的索引。

public int lastIndexOf(String str) {
        return lastIndexOf(str, value.length);
    }

 int lastIndexOf(String str, int startIndex) :从指定的索引处开始向后搜索,返回在此字符串中最后一次出现的指定子字符串的索引。

public int lastIndexOf(String str, int fromIndex) {
        return lastIndexOf(value, 0, value.length,
                str.value, 0, str.value.length, fromIndex);
    }

indexOf(int ch, int fromIndex),split(String regex, int limit)(???????)

replace(char oldChar, char newChar) :将原字符串中所有的oldChar字符都替换成newChar字符,返回一个新的字符串。

public String replace(CharSequence target, CharSequence replacement) {
        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
    }

 String replaceAll(String regex, String replacement):将匹配正则表达式regex的匹配项都替换成replacement字符串,返回一个新的字符串。

public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }
substring(int beginIndex) 返回一个从索引 beginIndex 开始一直到结尾的子字符串。
public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
equals(Object anObject)就是比较的是组成字符串的每一个字符是否相同,如果都相同则返回true,否则返回false
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;
    }

 hashCode()

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
 

 

原文地址:https://www.cnblogs.com/xiaofuzi123456/p/11355938.html