자바 소스 코드 분석의 String 클래스

38546 단어 Java
 * The class {@code String} includes methods for examining
 * individual characters of the sequence, for comparing strings, for
 * searching strings, for extracting substrings, and for creating a
 * copy of a string with all characters translated to uppercase or to
 * lowercase. 

이상 은 원본 주석 에 포 함 된 주요 방법 에 대한 소개 입 니 다.개인 번역 은 다음 과 같 습 니 다.
  • 문자열 비교 방법
  • 대소 문자 변환 방법
  • 문자열 을 검색 하 는 방법
  • 문자열 의 단일 문자 검사
  • 하위 문자열 을 추출 하 는 방법
  • 물론 원본 코드 를 볼 때 도 함께 쓰 는 또 다른 방법 도 있다.
    내부 구성원
     /** The value is used for character storage. */
     private final char value[];
     /** Cache the hash code for the string */
     private int hash; // Default to 0

    string 클래스 는 char 배열 을 사용 하여 문자열 을 저장 하고 이 문자열 은 final 형식 입 니 다.그래서 string 형식 이 변 하지 않 는 다 는 말 이 있 습 니 다.
    구조 함수
    원래 모두 7 개의 구조 함수 가 있 었 으 나 두 개의 폐기 가 더 이상 사용 되 지 않 았 다.그래서 여기 다섯 개 밖 에 없어 요.
    /**
         * Initializes a newly created {@code String} object so that it represents
         * an empty character sequence.  Note that use of this constructor is
         * unnecessary since Strings are immutable.
         */
        public String() {
            this.value = "".value;
        }

    이 구조 함 수 는 빈 문자 배열 을 만 들 것 이다.물론 이 구조 함 수 는 string 이 변 하지 않 을 때 쓸모 가 없다.
     /**
         * Initializes a newly created {@code String} object so that it represents
         * the same sequence of characters as the argument; in other words, the
         * newly created string is a copy of the argument string. Unless an
         * explicit copy of {@code original} is needed, use of this constructor is
         * unnecessary since Strings are immutable.
         *
         * @param  original
         *         A {@code String}
         */
        public String(String original) {
            this.value = original.value;
            this.hash = original.hash;
        }
    

    이 구조 함 수 는 이미 존재 하 는 string 류 를 사용 하여 새로운 것 을 구축 하 는 것 으로 복사 본 을 만 드 는 셈 이다.
    
        /**
         * Allocates a new {@code String} so that it represents the sequence of
         * characters currently contained in the character array argument. The
         * contents of the character array are copied; subsequent modification of
         * the character array does not affect the newly created string.
         *
         * @param  value
         *         The initial value of the string
         */
        public String(char value[]) {
            this.value = Arrays.copyOf(value, value.length);
        }

    char 배열 에 따라 string 을 초기 화 합 니 다. 여 기 는 Arrays 류 의 copy Of 함 수 를 사용 합 니 다.
     /**
         * Allocates a new {@code String} that contains characters from a subarray
         * of the character array argument. The {@code offset} argument is the
         * index of the first character of the subarray and the {@code count}
         * argument specifies the length of the subarray. The contents of the
         * subarray are copied; subsequent modification of the character array does
         * not affect the newly created string.
         *
         * @param  value
         *         Array that is the source of characters
         *
         * @param  offset
         *         The initial offset
         *
         * @param  count
         *         The length
         *
         * @throws  IndexOutOfBoundsException
         *          If the {@code offset} and {@code count} arguments index
         *          characters outside the bounds of the {@code value} array
         */
        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);
        }

    이 구조 방법 은 기 존의 char 배열 을 사용 하여 그 부분 을 복사 하여 문자열 을 만 드 는 것 입 니 다.복사 한 부분 은 offset 시작, count 길이 의 부분 입 니 다.사실 주요 호출 방법 은 Arrays 의 copy of Range 방법 입 니 다.
     public char charAt(int index) {
            if ((index < 0) || (index >= value.length)) {
                throw new StringIndexOutOfBoundsException(index);
            }
            return value[index];
        }

    charAt 방법, 이 방법 은 자 연 스 럽 게 배열 의 아래 표 시 된 값 에 따라 대응 하 는 값 을 되 돌려 주 는 것 입 니 다.
     /**
         * Compares this string to the specified object.  The result is {@code
         * true} if and only if the argument is not {@code null} and is a {@code
         * String} object that represents the same sequence of characters as this
         * object.
         *
         * @param  anObject
         *         The object to compare this {@code String} against
         *
         * @return  {@code true} if the given object represents a {@code String}
         *          equivalent to this string, {@code false} otherwise
         *
         * @see  #compareTo(String)
         * @see  #equalsIgnoreCase(String)
         */
        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;
        }

    equals 방법 은 두 대상 이 같 는 지 아 닌 지 를 판단 하 는 데 쓰 인 다.사용 하 는 구체 적 인 방법 은 두 대상 의 구성원 char 배열 의 모든 요소 가 같 는 지 여 부 를 하나씩 판단 하 는 것 이다.
     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;
        }

    compare To 방법 은 현재 문자열 과 비교 할 문자열 을 입력 합 니 다.대비 결 과 를 되돌리다.구체 적 인 정책 은 다음 과 같 습 니 다. 두 문자열 중 가장 짧 은 문자열 의 길 이 를 가 져 오고 이 를 제한 하여 이 두 문자열 의 배열 구성원 을 비교 합 니 다.다른 사람 이 있 으 면 현재 문자열 의 문자 값 을 되 돌려 대상 매개 변수 문자열 의 문자 값 차 이 를 줄 입 니 다.위의 과정 을 비교 한 후에 이들 의 모든 값 이 같다 면 두 문자열 의 길이 차 이 를 되 돌려 줍 니 다.
    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;
        }

    이것 이 바로 string 류 hashcode 의 구축 방법 입 니 다.원래 값 곱 하기 31 에 새 문자 값 추가...
    substring 방법 은 하위 문자열 을 가 져 오 는 데 사 용 됩 니 다.이 방법 은 두 가지 무 거 운 짐 을 싣 는 방법 이 있다.
        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);
        }

    두 번 째 실현
    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);
        }

    빈 칸 제거 trim 방법
     public String trim() {
            int len = value.length;
            int st = 0;
            char[] val = value;    /* avoid getfield opcode */
    
            while ((st < len) && (val[st] <= ' ')) {
                st++;
            }
            while ((st < len) && (val[len - 1] <= ' ')) {
                len--;
            }
            return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
        }

    대소 문자 변환
     public String toUpperCase(Locale locale) {
            if (locale == null) {
                throw new NullPointerException();
            }
    
            int firstLower;
            final int len = value.length;
    
            /* Now check if there are any characters that need to be changed. */
            scan: {
                for (firstLower = 0 ; firstLower < len; ) {
                    int c = (int)value[firstLower];
                    int srcCount;
                    if ((c >= Character.MIN_HIGH_SURROGATE)
                            && (c <= Character.MAX_HIGH_SURROGATE)) {
                        c = codePointAt(firstLower);
                        srcCount = Character.charCount(c);
                    } else {
                        srcCount = 1;
                    }
                    int upperCaseChar = Character.toUpperCaseEx(c);
                    if ((upperCaseChar == Character.ERROR)
                            || (c != upperCaseChar)) {
                        break scan;
                    }
                    firstLower += srcCount;
                }
                return this;
            }
    
            /* result may grow, so i+resultOffset is the write location in result */
            int resultOffset = 0;
            char[] result = new char[len]; /* may grow */
    
            /* Just copy the first few upperCase characters. */
            System.arraycopy(value, 0, result, 0, firstLower);
    
            String lang = locale.getLanguage();
            boolean localeDependent =
                    (lang == "tr" || lang == "az" || lang == "lt");
            char[] upperCharArray;
            int upperChar;
            int srcChar;
            int srcCount;
            for (int i = firstLower; i < len; i += srcCount) {
                srcChar = (int)value[i];
                if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
                    (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
                    srcChar = codePointAt(i);
                    srcCount = Character.charCount(srcChar);
                } else {
                    srcCount = 1;
                }
                if (localeDependent) {
                    upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
                } else {
                    upperChar = Character.toUpperCaseEx(srcChar);
                }
                if ((upperChar == Character.ERROR)
                        || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                    if (upperChar == Character.ERROR) {
                        if (localeDependent) {
                            upperCharArray =
                                    ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
                        } else {
                            upperCharArray = Character.toUpperCaseCharArray(srcChar);
                        }
                    } else if (srcCount == 2) {
                        resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;
                        continue;
                    } else {
                        upperCharArray = Character.toChars(upperChar);
                    }
    
                    /* Grow result if needed */
                    int mapLen = upperCharArray.length;
                    if (mapLen > srcCount) {
                        char[] result2 = new char[result.length + mapLen - srcCount];
                        System.arraycopy(result, 0, result2, 0, i + resultOffset);
                        result = result2;
                    }
                    for (int x = 0; x < mapLen; ++x) {
                        result[i + resultOffset + x] = upperCharArray[x];
                    }
                    resultOffset += (mapLen - srcCount);
                } else {
                    result[i + resultOffset] = (char)upperChar;
                }
            }
            return new String(result, 0, len + resultOffset);
        }
    

    소문 자로 변환
     public String toLowerCase(Locale locale) {
            if (locale == null) {
                throw new NullPointerException();
            }
    
            int firstUpper;
            final int len = value.length;
    
            /* Now check if there are any characters that need to be changed. */
            scan: {
                for (firstUpper = 0 ; firstUpper < len; ) {
                    char c = value[firstUpper];
                    if ((c >= Character.MIN_HIGH_SURROGATE)
                            && (c <= Character.MAX_HIGH_SURROGATE)) {
                        int supplChar = codePointAt(firstUpper);
                        if (supplChar != Character.toLowerCase(supplChar)) {
                            break scan;
                        }
                        firstUpper += Character.charCount(supplChar);
                    } else {
                        if (c != Character.toLowerCase(c)) {
                            break scan;
                        }
                        firstUpper++;
                    }
                }
                return this;
            }
    
            char[] result = new char[len];
            int resultOffset = 0;  /* result may grow, so i+resultOffset
                                    * is the write location in result */
    
            /* Just copy the first few lowerCase characters. */
            System.arraycopy(value, 0, result, 0, firstUpper);
    
            String lang = locale.getLanguage();
            boolean localeDependent =
                    (lang == "tr" || lang == "az" || lang == "lt");
            char[] lowerCharArray;
            int lowerChar;
            int srcChar;
            int srcCount;
            for (int i = firstUpper; i < len; i += srcCount) {
                srcChar = (int)value[i];
                if ((char)srcChar >= Character.MIN_HIGH_SURROGATE
                        && (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
                    srcChar = codePointAt(i);
                    srcCount = Character.charCount(srcChar);
                } else {
                    srcCount = 1;
                }
                if (localeDependent ||
                    srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
                    srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
                    lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
                } else {
                    lowerChar = Character.toLowerCase(srcChar);
                }
                if ((lowerChar == Character.ERROR)
                        || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                    if (lowerChar == Character.ERROR) {
                        lowerCharArray =
                                ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
                    } else if (srcCount == 2) {
                        resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
                        continue;
                    } else {
                        lowerCharArray = Character.toChars(lowerChar);
                    }
    
                    /* Grow result if needed */
                    int mapLen = lowerCharArray.length;
                    if (mapLen > srcCount) {
                        char[] result2 = new char[result.length + mapLen - srcCount];
                        System.arraycopy(result, 0, result2, 0, i + resultOffset);
                        result = result2;
                    }
                    for (int x = 0; x < mapLen; ++x) {
                        result[i + resultOffset + x] = lowerCharArray[x];
                    }
                    resultOffset += (mapLen - srcCount);
                } else {
                    result[i + resultOffset] = (char)lowerChar;
                }
            }
            return new String(result, 0, len + resultOffset);
        }

    문자열 분할 split 방법 정규 표현 식 기반 방법
      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 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);
        }

    replace 방법: 이 문자열 에 나타 난 모든 oldChar 를 new Char 로 대체 하여 얻 은 새로운 문자열 을 되 돌려 줍 니 다.
     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;
        }

    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);
        }

    좋은 웹페이지 즐겨찾기