• 学习JDK源码(一):String


      用了好久的Java了,从来没有看过jdk的源码,趁着今天有点时间,拿出了jdk的源码看了下,今天先看了关于String的,毕竟开发中String类型使用最广泛。在我们下载安装jdk的时候,部分源码也已经同时存放在我们电脑里了,具体路径为jdk目录下的src.zip压缩包,解压即可。

    java.lang.String

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

    这是String类的声明,很明显它是由final类型声明的,所以它不能被继承,而它又实现了Serializable接口,代表它是可以被序列化的。

    接着我们来看看类内部是怎么定义的

    /** The value is used for character storage. */
        private final char value[];

    使用final类型的字符数组存储字符串内容,String初始化后就不能被改变。

    有一种写法,String s = “abc”; s = “bcd”;当然这并不是改变了字符串s的值,只是将s指向了一个新的字符串,所以千万不要以为字符串是可以变的。

    /** Cache the hash code for the string */
        private int hash; // Default to 0

    指定缓存字符串的hash code的值,默认为0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
        private static final long serialVersionUID = -6849794470754667710L;
    相当于java类的身份证。主要用于版本控制。
    serialVersionUID作用是序列化时保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
    有两种生成方式:
    一个是默认的1L,比如:private static final long serialVersionUID = 1L;
    一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
    private static final long serialVersionUID = xxxxL;
    /**
         * 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>
         */
        private static final ObjectStreamField[] serialPersistentFields =
            new ObjectStreamField[0];
    serialPersistentFields 用于指定哪些字段需要被默认序列化,如:
    private static final ObjectStreamField[] serialPersistentFields =    
    {  
        new ObjectStreamField("name", String.class),   
        new ObjectStreamField("a", Integer.TYPE)   
    }; 
    看了String类的构造方法,惊叹不已,源码中有足足15种构造方法,其中最常用的不外乎以下几种
    public String(byte bytes[]) {
            this(bytes, 0, bytes.length);
        }
    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类自身提供的一系列方法了:
    // 返回字符串的长度  
        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];
        }
        // 返回指定索引处的字符
        public int codePointAt(int index) {
            if ((index < 0) || (index >= value.length)) {
                throw new StringIndexOutOfBoundsException(index);
            }
            return Character.codePointAtImpl(value, index, value.length);
        }
        // 返回指定索引之前的字符
        public int codePointBefore(int index) {
            int i = index - 1;
            if ((i < 0) || (i >= value.length)) {
                throw new StringIndexOutOfBoundsException(index);
            }
            return Character.codePointBeforeImpl(value, index, 0);
        }
        // 返回此 String 的指定文本范围中的 Unicode 代码点数
        public int codePointCount(int beginIndex, int endIndex) {
            if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
                throw new IndexOutOfBoundsException();
            }
            return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
        }
    //返回从0处开始的第i个Code Point的位置
    public int offsetByCodePoints(int index, int codePointOffset) {
            if (index < 0 || index > value.length) {
                throw new IndexOutOfBoundsException();
            }
            return Character.offsetByCodePointsImpl(value, 0, value.length,
                    index, codePointOffset);
        }
        //判断两个字符串是否相等
    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;
        }
        //不区分大小写的情况下比较两个字符串是否相等
    public boolean equalsIgnoreCase(String anotherString) {
            return (this == anotherString) ? true
                    : (anotherString != null)
                    && (anotherString.value.length == value.length)
                    && regionMatches(true, 0, anotherString, 0, value.length);
        }
    //计算当前字符串比目标字符串长度大多少
    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 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;
        }
    //返回某个指定的字符串值在字符串中首次出现的位置
    public int indexOf(int ch) {
            return indexOf(ch, 0);
        }
    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;
            }
    
            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 char[] value = this.value;
                for (int i = fromIndex; i < max; i++) {
                    if (value[i] == ch) {
                        return i;
                    }
                }
                return -1;
            } else {
                return indexOfSupplementary(ch, fromIndex);
            }
        }
    //返回某个指定的字符串值在字符串中最后一次出现的位置
    public int lastIndexOf(int ch) {
            return lastIndexOf(ch, value.length - 1);
        }
    public int lastIndexOf(int ch, int fromIndex) {
            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 char[] value = this.value;
                int i = Math.min(fromIndex, value.length - 1);
                for (; i >= 0; i--) {
                    if (value[i] == ch) {
                        return i;
                    }
                }
                return -1;
            } else {
                return lastIndexOfSupplementary(ch, fromIndex);
            }
        }
    //从指定位置截取字符串直至最后一位
    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);
        }
    //截取字符串从beginIndex至beginIndex
    public String substring(int beginIndex, int endIndex) {
            if (beginIndex < 0) {
                throw new StringIndexOutOfBoundsException(beginIndex);
            }
            if (endIndex > value.length) {
                throw new StringIndexOutOfBoundsException(endIndex);
            }
            int subLen = endIndex - beginIndex;
            if (subLen < 0) {
                throw new StringIndexOutOfBoundsException(subLen);
            }
            return ((beginIndex == 0) && (endIndex == value.length)) ? this
                    : new String(value, beginIndex, subLen);
        }
    //字符串拼接
    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);
     }
    //字符串替换
    public String replace(char oldChar, char newChar) {
            if (oldChar != newChar) {
                int len = value.length;
                int i = -1;
                char[] val = value; /* avoid getfield opcode */
    
                while (++i < len) {
                    if (val[i] == oldChar) {
                        break;
                    }
                }
                if (i < len) {
                    char buf[] = new char[len];
                    for (int j = 0; j < i; j++) {
                        buf[j] = val[j];
                    }
                    while (i < len) {
                        char c = val[i];
                        buf[i] = (c == oldChar) ? newChar : c;
                        i++;
                    }
                    return new String(buf, true);
                }
            }
            return this;
        }
    //判断字符串是否包含在另一个字符串中
    public boolean contains(CharSequence s) {
            return indexOf(s.toString()) > -1;
        }
    //将目标字符串中匹配的字符全部替换成另一字符串
    public String replaceAll(String regex, String replacement) {
            return Pattern.compile(regex).matcher(this).replaceAll(replacement);
        }
    //按约定分隔符将目标字符串分割成多个字符串并返回字符串数组
    public String[] split(String regex, int limit) {
            /* fastpath if the regex is a
             (1)one-char String and this character is not one of the
                RegEx's meta characters ".$|()[{^?*+\", or
             (2)two-char String and the first char is the backslash and
                the second is not the ascii digit or ascii letter.
             */
            char ch = 0;
            if (((regex.value.length == 1 &&
                 ".$|()[{^?*+\".indexOf(ch = regex.charAt(0)) == -1) ||
                 (regex.length() == 2 &&
                  regex.charAt(0) == '\' &&
                  (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
                  ((ch-'a')|('z'-ch)) < 0 &&
                  ((ch-'A')|('Z'-ch)) < 0)) &&
                (ch < Character.MIN_HIGH_SURROGATE ||
                 ch > Character.MAX_LOW_SURROGATE))
            {
                int off = 0;
                int next = 0;
                boolean limited = limit > 0;
                ArrayList<String> list = new ArrayList<>();
                while ((next = indexOf(ch, off)) != -1) {
                    if (!limited || list.size() < limit - 1) {
                        list.add(substring(off, next));
                        off = next + 1;
                    } else {    // last one
                        //assert (list.size() == limit - 1);
                        list.add(substring(off, value.length));
                        off = value.length;
                        break;
                    }
                }
                // If no match was found, return this
                if (off == 0)
                    return new String[]{this};
    
                // Add remaining segment
                if (!limited || list.size() < limit)
                    list.add(substring(off, value.length));
    
                // Construct result
                int resultSize = list.size();
                if (limit == 0) {
                    while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                        resultSize--;
                    }
                }
                String[] result = new String[resultSize];
                return list.subList(0, resultSize).toArray(result);
            }
            return Pattern.compile(regex).split(this, limit);
        }
     
    
    
    
     
  • 相关阅读:
    veil-evasion免杀处理
    对程序"加料"
    堆栈溢出
    ICMP隧道 ptunnle
    socat流量操控
    DNS隧道 iodns
    dns隧道 dns2tcpd
    ssh X协议转发
    ssh动态端口转发
    ssh远程端口转发
  • 原文地址:https://www.cnblogs.com/timePasser-leoli/p/7873311.html
Copyright © 2020-2023  润新知