JDK

java.lang.Characterクラス

Characterクラスは名前の通り文字を扱うためのクラスで,元々のソースコードは1万行以上もある巨大なものである。以下のソースコードは一部を省略したコードである。世界のほとんどの言語を網羅しているため,それぞれの言語ごとの範囲を定義している部分が大きな割合を占めている。ほとんどがリテラル定義となっている。実際に処理を行うメソッドは少なく,また特に説明を要するような難解なメソッドもない。

/*
 * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.Locale;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.VM;
public final
class Character implements java.io.Serializable, Comparable<Character> {
    public static final int MIN_RADIX = 2;
    public static final int MAX_RADIX = 36;
    public static final char MIN_VALUE = '\u0000';
    public static final char MAX_VALUE = '\uFFFF';
    @SuppressWarnings("unchecked")
    public static final Class<Character> TYPE = (Class<Character>) Class.getPrimitiveClass("char");
    /*
     * Normative general types
     */
    /*
     * General character types
     */
    public static final byte UNASSIGNED = 0;
    public static final byte UPPERCASE_LETTER = 1;
    public static final byte LOWERCASE_LETTER = 2;
    public static final byte TITLECASE_LETTER = 3;
    public static final byte MODIFIER_LETTER = 4;
    public static final byte OTHER_LETTER = 5;
    public static final byte NON_SPACING_MARK = 6;
    public static final byte ENCLOSING_MARK = 7;
    public static final byte COMBINING_SPACING_MARK = 8;
    public static final byte DECIMAL_DIGIT_NUMBER        = 9;
    public static final byte LETTER_NUMBER = 10;
    public static final byte OTHER_NUMBER = 11;
    public static final byte SPACE_SEPARATOR = 12;
    public static final byte LINE_SEPARATOR = 13;
    public static final byte PARAGRAPH_SEPARATOR = 14;
    public static final byte CONTROL = 15;
    public static final byte FORMAT = 16;
    public static final byte PRIVATE_USE = 18;
    public static final byte SURROGATE = 19;
    public static final byte DASH_PUNCTUATION = 20;
    public static final byte START_PUNCTUATION = 21;
    public static final byte END_PUNCTUATION = 22;
    public static final byte CONNECTOR_PUNCTUATION = 23;
    public static final byte OTHER_PUNCTUATION = 24;
    public static final byte MATH_SYMBOL = 25;
    public static final byte CURRENCY_SYMBOL = 26;
    public static final byte MODIFIER_SYMBOL = 27;
    public static final byte OTHER_SYMBOL = 28;
    public static final byte INITIAL_QUOTE_PUNCTUATION = 29;
    public static final byte FINAL_QUOTE_PUNCTUATION = 30;
    static final int ERROR = 0xFFFFFFFF;
    public static final byte DIRECTIONALITY_UNDEFINED = -1;
    public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0;
    public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1;
    public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2;
    public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 3;
    public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4;
    public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5;
    public static final byte DIRECTIONALITY_ARABIC_NUMBER = 6;
    public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7;
    public static final byte DIRECTIONALITY_NONSPACING_MARK = 8;
    public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 9;
    public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10;
    public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 11;
    public static final byte DIRECTIONALITY_WHITESPACE = 12;
    public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 13;
    public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14;
    public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15;
    public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16;
    public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17;
    public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18;
    public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE = 19;
    public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE = 20;
    public static final byte DIRECTIONALITY_FIRST_STRONG_ISOLATE = 21;
    public static final byte DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE = 22;
    public static final char MIN_HIGH_SURROGATE = '\uD800';
    public static final char MAX_HIGH_SURROGATE = '\uDBFF';
    public static final char MIN_LOW_SURROGATE  = '\uDC00';
    public static final char MAX_LOW_SURROGATE  = '\uDFFF';
    public static final char MIN_SURROGATE = MIN_HIGH_SURROGATE;
    public static final char MAX_SURROGATE = MAX_LOW_SURROGATE;
    public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
    public static final int MIN_CODE_POINT = 0x000000;
    public static final int MAX_CODE_POINT = 0X10FFFF;
    public static class Subset  {
        private String name;
        protected Subset(String name) {
            if (name == null) {
                throw new NullPointerException("name");
            }
            this.name = name;
        }
        public final boolean equals(Object obj) {
            return (this == obj);
        }
        public final int hashCode() {
            return super.hashCode();
        }
        public final String toString() {
            return name;
        }
    }
    // See http://www.unicode.org/Public/UNIDATA/Blocks.txt
    // for the latest specification of Unicode Blocks.
    public static final class UnicodeBlock extends Subset {
        private static final int NUM_ENTITIES = 667;
        private static Map<String, UnicodeBlock> map =
                new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f));
        private UnicodeBlock(String idName) {
            super(idName);
            map.put(idName, this);
        }
        private UnicodeBlock(String idName, String alias) {
            this(idName);
            map.put(alias, this);
        }
        private UnicodeBlock(String idName, String… aliases) {
            this(idName);
            for (String alias : aliases)
                map.put(alias, this);
        }
        public static final UnicodeBlock  BASIC_LATIN =
            new UnicodeBlock("BASIC_LATIN",
                             "BASIC LATIN",
                             "BASICLATIN");
        public static final UnicodeBlock LATIN_1_SUPPLEMENT =
            new UnicodeBlock("LATIN_1_SUPPLEMENT",
                             "LATIN-1 SUPPLEMENT",
                             "LATIN-1SUPPLEMENT");
        public static final UnicodeBlock LATIN_EXTENDED_A =
            new UnicodeBlock("LATIN_EXTENDED_A",
                             "LATIN EXTENDED-A",
                             "LATINEXTENDED-A");
        public static final UnicodeBlock LATIN_EXTENDED_B =
            new UnicodeBlock("LATIN_EXTENDED_B",
                             "LATIN EXTENDED-B",
                             "LATINEXTENDED-B");
        public static final UnicodeBlock IPA_EXTENSIONS =
            new UnicodeBlock("IPA_EXTENSIONS",
                             "IPA EXTENSIONS",
                             "IPAEXTENSIONS");
        public static final UnicodeBlock SPACING_MODIFIER_LETTERS =
            new UnicodeBlock("SPACING_MODIFIER_LETTERS",
                             "SPACING MODIFIER LETTERS",
                             "SPACINGMODIFIERLETTERS");
        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS =
            new UnicodeBlock("COMBINING_DIACRITICAL_MARKS",
                             "COMBINING DIACRITICAL MARKS",
                             "COMBININGDIACRITICALMARKS");
        public static final UnicodeBlock GREEK =
            new UnicodeBlock("GREEK",
                             "GREEK AND COPTIC",
                             "GREEKANDCOPTIC");
        public static final UnicodeBlock CYRILLIC =
            new UnicodeBlock("CYRILLIC");
        public static final UnicodeBlock ARMENIAN =
            new UnicodeBlock("ARMENIAN");
        public static final UnicodeBlock HEBREW =
            new UnicodeBlock("HEBREW");
        public static final UnicodeBlock ARABIC =
            new UnicodeBlock("ARABIC");
        public static final UnicodeBlock DEVANAGARI =
            new UnicodeBlock("DEVANAGARI");
        public static final UnicodeBlock BENGALI =
            new UnicodeBlock("BENGALI");
        public static final UnicodeBlock GURMUKHI =
            new UnicodeBlock("GURMUKHI");
        public static final UnicodeBlock GUJARATI =
            new UnicodeBlock("GUJARATI");
        public static final UnicodeBlock ORIYA =
            new UnicodeBlock("ORIYA");
        public static final UnicodeBlock TAMIL =
            new UnicodeBlock("TAMIL");
        public static final UnicodeBlock TELUGU =
            new UnicodeBlock("TELUGU");
        public static final UnicodeBlock KANNADA =
            new UnicodeBlock("KANNADA");
        public static final UnicodeBlock MALAYALAM =
            new UnicodeBlock("MALAYALAM");
        public static final UnicodeBlock THAI =
            new UnicodeBlock("THAI");
        public static final UnicodeBlock LAO =
            new UnicodeBlock("LAO");
        public static final UnicodeBlock TIBETAN =
            new UnicodeBlock("TIBETAN");
        public static final UnicodeBlock GEORGIAN =
            new UnicodeBlock("GEORGIAN");
        public static final UnicodeBlock HANGUL_JAMO =
            new UnicodeBlock("HANGUL_JAMO",
                             "HANGUL JAMO",
                             "HANGULJAMO");
        public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL =
            new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL",
                             "LATIN EXTENDED ADDITIONAL",
                             "LATINEXTENDEDADDITIONAL");
        public static final UnicodeBlock GREEK_EXTENDED =
            new UnicodeBlock("GREEK_EXTENDED",
                             "GREEK EXTENDED",
                             "GREEKEXTENDED");
        public static final UnicodeBlock GENERAL_PUNCTUATION =
            new UnicodeBlock("GENERAL_PUNCTUATION",
                             "GENERAL PUNCTUATION",
                             "GENERALPUNCTUATION");
        public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS =
            new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS",
                             "SUPERSCRIPTS AND SUBSCRIPTS",
                             "SUPERSCRIPTSANDSUBSCRIPTS");
        public static final UnicodeBlock CURRENCY_SYMBOLS =
            new UnicodeBlock("CURRENCY_SYMBOLS",
                             "CURRENCY SYMBOLS",
                             "CURRENCYSYMBOLS");
        public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS =
            new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS",
                             "COMBINING DIACRITICAL MARKS FOR SYMBOLS",
                             "COMBININGDIACRITICALMARKSFORSYMBOLS",
                             "COMBINING MARKS FOR SYMBOLS",
                             "COMBININGMARKSFORSYMBOLS");
        public static final UnicodeBlock LETTERLIKE_SYMBOLS =
            new UnicodeBlock("LETTERLIKE_SYMBOLS",
                             "LETTERLIKE SYMBOLS",
                             "LETTERLIKESYMBOLS");
        public static final UnicodeBlock NUMBER_FORMS =
            new UnicodeBlock("NUMBER_FORMS",
                             "NUMBER FORMS",
                             "NUMBERFORMS");
        public static final UnicodeBlock ARROWS =
            new UnicodeBlock("ARROWS");
        public static final UnicodeBlock MATHEMATICAL_OPERATORS =
            new UnicodeBlock("MATHEMATICAL_OPERATORS",
                             "MATHEMATICAL OPERATORS",
                             "MATHEMATICALOPERATORS");
        public static final UnicodeBlock MISCELLANEOUS_TECHNICAL =
            new UnicodeBlock("MISCELLANEOUS_TECHNICAL",
                             "MISCELLANEOUS TECHNICAL",
                             "MISCELLANEOUSTECHNICAL");
        public static final UnicodeBlock CONTROL_PICTURES =
            new UnicodeBlock("CONTROL_PICTURES",
                             "CONTROL PICTURES",
                             "CONTROLPICTURES");
        public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION =
            new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION",
                             "OPTICAL CHARACTER RECOGNITION",
                             "OPTICALCHARACTERRECOGNITION");
        public static final UnicodeBlock ENCLOSED_ALPHANUMERICS =
            new UnicodeBlock("ENCLOSED_ALPHANUMERICS",
                             "ENCLOSED ALPHANUMERICS",
                             "ENCLOSEDALPHANUMERICS");
        public static final UnicodeBlock BOX_DRAWING =
            new UnicodeBlock("BOX_DRAWING",
                             "BOX DRAWING",
                             "BOXDRAWING");
        public static final UnicodeBlock BLOCK_ELEMENTS =
            new UnicodeBlock("BLOCK_ELEMENTS",
                             "BLOCK ELEMENTS",
                             "BLOCKELEMENTS");
        public static final UnicodeBlock GEOMETRIC_SHAPES =
            new UnicodeBlock("GEOMETRIC_SHAPES",
                             "GEOMETRIC SHAPES",
                             "GEOMETRICSHAPES");
        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS =
            new UnicodeBlock("MISCELLANEOUS_SYMBOLS",
                             "MISCELLANEOUS SYMBOLS",
                             "MISCELLANEOUSSYMBOLS");
        public static final UnicodeBlock DINGBATS =
            new UnicodeBlock("DINGBATS");
        public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION =
            new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION",
                             "CJK SYMBOLS AND PUNCTUATION",
                             "CJKSYMBOLSANDPUNCTUATION");
        public static final UnicodeBlock HIRAGANA =
            new UnicodeBlock("HIRAGANA");
        public static final UnicodeBlock KATAKANA =
            new UnicodeBlock("KATAKANA");
        public static final UnicodeBlock BOPOMOFO =
            new UnicodeBlock("BOPOMOFO");
        public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO =
            new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO",
                             "HANGUL COMPATIBILITY JAMO",
                             "HANGULCOMPATIBILITYJAMO");
        public static final UnicodeBlock KANBUN =
            new UnicodeBlock("KANBUN");
        public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS =
            new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS",
                             "ENCLOSED CJK LETTERS AND MONTHS",
                             "ENCLOSEDCJKLETTERSANDMONTHS");
        public static final UnicodeBlock CJK_COMPATIBILITY =
            new UnicodeBlock("CJK_COMPATIBILITY",
                             "CJK COMPATIBILITY",
                             "CJKCOMPATIBILITY");
        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS =
            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS",
                             "CJK UNIFIED IDEOGRAPHS",
                             "CJKUNIFIEDIDEOGRAPHS");
        public static final UnicodeBlock HANGUL_SYLLABLES =
            new UnicodeBlock("HANGUL_SYLLABLES",
                             "HANGUL SYLLABLES",
                             "HANGULSYLLABLES");
        public static final UnicodeBlock PRIVATE_USE_AREA =
            new UnicodeBlock("PRIVATE_USE_AREA",
                             "PRIVATE USE AREA",
                             "PRIVATEUSEAREA");
        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS =
            new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS",
                             "CJK COMPATIBILITY IDEOGRAPHS",
                             "CJKCOMPATIBILITYIDEOGRAPHS");
        public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS =
            new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS",
                             "ALPHABETIC PRESENTATION FORMS",
                             "ALPHABETICPRESENTATIONFORMS");
        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A =
            new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A",
                             "ARABIC PRESENTATION FORMS-A",
                             "ARABICPRESENTATIONFORMS-A");
        public static final UnicodeBlock COMBINING_HALF_MARKS =
            new UnicodeBlock("COMBINING_HALF_MARKS",
                             "COMBINING HALF MARKS",
                             "COMBININGHALFMARKS");
        public static final UnicodeBlock CJK_COMPATIBILITY_FORMS =
            new UnicodeBlock("CJK_COMPATIBILITY_FORMS",
                             "CJK COMPATIBILITY FORMS",
                             "CJKCOMPATIBILITYFORMS");
        public static final UnicodeBlock SMALL_FORM_VARIANTS =
            new UnicodeBlock("SMALL_FORM_VARIANTS",
                             "SMALL FORM VARIANTS",
                             "SMALLFORMVARIANTS");
        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B =
            new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B",
                             "ARABIC PRESENTATION FORMS-B",
                             "ARABICPRESENTATIONFORMS-B");
        public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS =
            new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS",
                             "HALFWIDTH AND FULLWIDTH FORMS",
                             "HALFWIDTHANDFULLWIDTHFORMS");
        public static final UnicodeBlock SPECIALS =
            new UnicodeBlock("SPECIALS");
        @Deprecated(since="1.5")
        public static final UnicodeBlock SURROGATES_AREA =
            new UnicodeBlock("SURROGATES_AREA");
        public static final UnicodeBlock SYRIAC =
            new UnicodeBlock("SYRIAC");
        public static final UnicodeBlock THAANA =
            new UnicodeBlock("THAANA");
        public static final UnicodeBlock SINHALA =
            new UnicodeBlock("SINHALA");
        public static final UnicodeBlock MYANMAR =
            new UnicodeBlock("MYANMAR");
        public static final UnicodeBlock ETHIOPIC =
            new UnicodeBlock("ETHIOPIC");
        public static final UnicodeBlock CHEROKEE =
            new UnicodeBlock("CHEROKEE");
        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS =
            new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS",
                             "UNIFIED CANADIAN ABORIGINAL SYLLABICS",
                             "UNIFIEDCANADIANABORIGINALSYLLABICS");
        public static final UnicodeBlock OGHAM =
            new UnicodeBlock("OGHAM");
        public static final UnicodeBlock RUNIC =
            new UnicodeBlock("RUNIC");
        public static final UnicodeBlock KHMER =
            new UnicodeBlock("KHMER");
        public static final UnicodeBlock MONGOLIAN =
            new UnicodeBlock("MONGOLIAN");
        public static final UnicodeBlock BRAILLE_PATTERNS =
            new UnicodeBlock("BRAILLE_PATTERNS",
                             "BRAILLE PATTERNS",
                             "BRAILLEPATTERNS");
        public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT =
            new UnicodeBlock("CJK_RADICALS_SUPPLEMENT",
                             "CJK RADICALS SUPPLEMENT",
                             "CJKRADICALSSUPPLEMENT");
        public static final UnicodeBlock KANGXI_RADICALS =
            new UnicodeBlock("KANGXI_RADICALS",
                             "KANGXI RADICALS",
                             "KANGXIRADICALS");
        public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS =
            new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS",
                             "IDEOGRAPHIC DESCRIPTION CHARACTERS",
                             "IDEOGRAPHICDESCRIPTIONCHARACTERS");
        public static final UnicodeBlock BOPOMOFO_EXTENDED =
            new UnicodeBlock("BOPOMOFO_EXTENDED",
                             "BOPOMOFO EXTENDED",
                             "BOPOMOFOEXTENDED");
        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A =
            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A",
                             "CJK UNIFIED IDEOGRAPHS EXTENSION A",
                             "CJKUNIFIEDIDEOGRAPHSEXTENSIONA");
        public static final UnicodeBlock YI_SYLLABLES =
            new UnicodeBlock("YI_SYLLABLES",
                             "YI SYLLABLES",
                             "YISYLLABLES");
        public static final UnicodeBlock YI_RADICALS =
            new UnicodeBlock("YI_RADICALS",
                             "YI RADICALS",
                             "YIRADICALS");
        public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY =
            new UnicodeBlock("CYRILLIC_SUPPLEMENTARY",
                             "CYRILLIC SUPPLEMENTARY",
                             "CYRILLICSUPPLEMENTARY",
                             "CYRILLIC SUPPLEMENT",
                             "CYRILLICSUPPLEMENT");
        public static final UnicodeBlock TAGALOG =
            new UnicodeBlock("TAGALOG");
        public static final UnicodeBlock HANUNOO =
            new UnicodeBlock("HANUNOO");
        public static final UnicodeBlock BUHID =
            new UnicodeBlock("BUHID");
        public static final UnicodeBlock TAGBANWA =
            new UnicodeBlock("TAGBANWA");
        public static final UnicodeBlock LIMBU =
            new UnicodeBlock("LIMBU");
        public static final UnicodeBlock TAI_LE =
            new UnicodeBlock("TAI_LE",
                             "TAI LE",
                             "TAILE");
        public static final UnicodeBlock KHMER_SYMBOLS =
            new UnicodeBlock("KHMER_SYMBOLS",
                             "KHMER SYMBOLS",
                             "KHMERSYMBOLS");
        public static final UnicodeBlock PHONETIC_EXTENSIONS =
            new UnicodeBlock("PHONETIC_EXTENSIONS",
                             "PHONETIC EXTENSIONS",
                             "PHONETICEXTENSIONS");
        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A =
            new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A",
                             "MISCELLANEOUS MATHEMATICAL SYMBOLS-A",
                             "MISCELLANEOUSMATHEMATICALSYMBOLS-A");
        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A =
            new UnicodeBlock("SUPPLEMENTAL_ARROWS_A",
                             "SUPPLEMENTAL ARROWS-A",
                             "SUPPLEMENTALARROWS-A");
        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B =
            new UnicodeBlock("SUPPLEMENTAL_ARROWS_B",
                             "SUPPLEMENTAL ARROWS-B",
                             "SUPPLEMENTALARROWS-B");
        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B =
            new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B",
                             "MISCELLANEOUS MATHEMATICAL SYMBOLS-B",
                             "MISCELLANEOUSMATHEMATICALSYMBOLS-B");
        public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS =
            new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS",
                             "SUPPLEMENTAL MATHEMATICAL OPERATORS",
                             "SUPPLEMENTALMATHEMATICALOPERATORS");
        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS =
            new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS",
                             "MISCELLANEOUS SYMBOLS AND ARROWS",
                             "MISCELLANEOUSSYMBOLSANDARROWS");
        public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS =
            new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS",
                             "KATAKANA PHONETIC EXTENSIONS",
                             "KATAKANAPHONETICEXTENSIONS");
        public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS =
            new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS",
                             "YIJING HEXAGRAM SYMBOLS",
                             "YIJINGHEXAGRAMSYMBOLS");
        public static final UnicodeBlock VARIATION_SELECTORS =
            new UnicodeBlock("VARIATION_SELECTORS",
                             "VARIATION SELECTORS",
                             "VARIATIONSELECTORS");
        public static final UnicodeBlock LINEAR_B_SYLLABARY =
            new UnicodeBlock("LINEAR_B_SYLLABARY",
                             "LINEAR B SYLLABARY",
                             "LINEARBSYLLABARY");
        public static final UnicodeBlock LINEAR_B_IDEOGRAMS =
            new UnicodeBlock("LINEAR_B_IDEOGRAMS",
                             "LINEAR B IDEOGRAMS",
                             "LINEARBIDEOGRAMS");
        public static final UnicodeBlock AEGEAN_NUMBERS =
            new UnicodeBlock("AEGEAN_NUMBERS",
                             "AEGEAN NUMBERS",
                             "AEGEANNUMBERS");
        public static final UnicodeBlock OLD_ITALIC =
            new UnicodeBlock("OLD_ITALIC",
                             "OLD ITALIC",
                             "OLDITALIC");
        public static final UnicodeBlock GOTHIC =
            new UnicodeBlock("GOTHIC");
        public static final UnicodeBlock UGARITIC =
            new UnicodeBlock("UGARITIC");
        public static final UnicodeBlock DESERET =
            new UnicodeBlock("DESERET");
        public static final UnicodeBlock SHAVIAN =
            new UnicodeBlock("SHAVIAN");
        public static final UnicodeBlock OSMANYA =
            new UnicodeBlock("OSMANYA");
        public static final UnicodeBlock CYPRIOT_SYLLABARY =
            new UnicodeBlock("CYPRIOT_SYLLABARY",
                             "CYPRIOT SYLLABARY",
                             "CYPRIOTSYLLABARY");
        public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS =
            new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS",
                             "BYZANTINE MUSICAL SYMBOLS",
                             "BYZANTINEMUSICALSYMBOLS");
        public static final UnicodeBlock MUSICAL_SYMBOLS =
            new UnicodeBlock("MUSICAL_SYMBOLS",
                             "MUSICAL SYMBOLS",
                             "MUSICALSYMBOLS");
        public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS =
            new UnicodeBlock("TAI_XUAN_JING_SYMBOLS",
                             "TAI XUAN JING SYMBOLS",
                             "TAIXUANJINGSYMBOLS");
        public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS =
            new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS",
                             "MATHEMATICAL ALPHANUMERIC SYMBOLS",
                             "MATHEMATICALALPHANUMERICSYMBOLS");
        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B =
            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B",
                             "CJK UNIFIED IDEOGRAPHS EXTENSION B",
                             "CJKUNIFIEDIDEOGRAPHSEXTENSIONB");
        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT =
            new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT",
                             "CJK COMPATIBILITY IDEOGRAPHS SUPPLEMENT",
                             "CJKCOMPATIBILITYIDEOGRAPHSSUPPLEMENT");
        public static final UnicodeBlock TAGS =
            new UnicodeBlock("TAGS");
        public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT =
            new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT",
                             "VARIATION SELECTORS SUPPLEMENT",
                             "VARIATIONSELECTORSSUPPLEMENT");
        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A =
            new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A",
                             "SUPPLEMENTARY PRIVATE USE AREA-A",
                             "SUPPLEMENTARYPRIVATEUSEAREA-A");
        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B =
            new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B",
                             "SUPPLEMENTARY PRIVATE USE AREA-B",
                             "SUPPLEMENTARYPRIVATEUSEAREA-B");
        public static final UnicodeBlock HIGH_SURROGATES =
            new UnicodeBlock("HIGH_SURROGATES",
                             "HIGH SURROGATES",
                             "HIGHSURROGATES");
        public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES =
            new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES",
                             "HIGH PRIVATE USE SURROGATES",
                             "HIGHPRIVATEUSESURROGATES");
        public static final UnicodeBlock LOW_SURROGATES =
            new UnicodeBlock("LOW_SURROGATES",
                             "LOW SURROGATES",
                             "LOWSURROGATES");
        public static final UnicodeBlock ARABIC_SUPPLEMENT =
            new UnicodeBlock("ARABIC_SUPPLEMENT",
                             "ARABIC SUPPLEMENT",
                             "ARABICSUPPLEMENT");
        public static final UnicodeBlock NKO =
            new UnicodeBlock("NKO");
        public static final UnicodeBlock SAMARITAN =
            new UnicodeBlock("SAMARITAN");
        public static final UnicodeBlock MANDAIC =
            new UnicodeBlock("MANDAIC");
        public static final UnicodeBlock ETHIOPIC_SUPPLEMENT =
            new UnicodeBlock("ETHIOPIC_SUPPLEMENT",
                             "ETHIOPIC SUPPLEMENT",
                             "ETHIOPICSUPPLEMENT");
        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED =
            new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED",
                             "UNIFIED CANADIAN ABORIGINAL SYLLABICS EXTENDED",
                             "UNIFIEDCANADIANABORIGINALSYLLABICSEXTENDED");
        public static final UnicodeBlock NEW_TAI_LUE =
            new UnicodeBlock("NEW_TAI_LUE",
                             "NEW TAI LUE",
                             "NEWTAILUE");
        public static final UnicodeBlock BUGINESE =
            new UnicodeBlock("BUGINESE");
        public static final UnicodeBlock TAI_THAM =
            new UnicodeBlock("TAI_THAM",
                             "TAI THAM",
                             "TAITHAM");
        public static final UnicodeBlock BALINESE =
            new UnicodeBlock("BALINESE");
        public static final UnicodeBlock SUNDANESE =
            new UnicodeBlock("SUNDANESE");
        public static final UnicodeBlock BATAK =
            new UnicodeBlock("BATAK");
        public static final UnicodeBlock LEPCHA =
            new UnicodeBlock("LEPCHA");
        public static final UnicodeBlock OL_CHIKI =
            new UnicodeBlock("OL_CHIKI",
                             "OL CHIKI",
                             "OLCHIKI");
        public static final UnicodeBlock VEDIC_EXTENSIONS =
            new UnicodeBlock("VEDIC_EXTENSIONS",
                             "VEDIC EXTENSIONS",
                             "VEDICEXTENSIONS");
        public static final UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT =
            new UnicodeBlock("PHONETIC_EXTENSIONS_SUPPLEMENT",
                             "PHONETIC EXTENSIONS SUPPLEMENT",
                             "PHONETICEXTENSIONSSUPPLEMENT");
        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT =
            new UnicodeBlock("COMBINING_DIACRITICAL_MARKS_SUPPLEMENT",
                             "COMBINING DIACRITICAL MARKS SUPPLEMENT",
                             "COMBININGDIACRITICALMARKSSUPPLEMENT");
        public static final UnicodeBlock GLAGOLITIC =
            new UnicodeBlock("GLAGOLITIC");
        public static final UnicodeBlock LATIN_EXTENDED_C =
            new UnicodeBlock("LATIN_EXTENDED_C",
                             "LATIN EXTENDED-C",
                             "LATINEXTENDED-C");
        public static final UnicodeBlock COPTIC =
            new UnicodeBlock("COPTIC");
        public static final UnicodeBlock GEORGIAN_SUPPLEMENT =
            new UnicodeBlock("GEORGIAN_SUPPLEMENT",
                             "GEORGIAN SUPPLEMENT",
                             "GEORGIANSUPPLEMENT");
        public static final UnicodeBlock TIFINAGH =
            new UnicodeBlock("TIFINAGH");
        public static final UnicodeBlock ETHIOPIC_EXTENDED =
            new UnicodeBlock("ETHIOPIC_EXTENDED",
                             "ETHIOPIC EXTENDED",
                             "ETHIOPICEXTENDED");
        public static final UnicodeBlock CYRILLIC_EXTENDED_A =
            new UnicodeBlock("CYRILLIC_EXTENDED_A",
                             "CYRILLIC EXTENDED-A",
                             "CYRILLICEXTENDED-A");
        public static final UnicodeBlock SUPPLEMENTAL_PUNCTUATION =
            new UnicodeBlock("SUPPLEMENTAL_PUNCTUATION",
                             "SUPPLEMENTAL PUNCTUATION",
                             "SUPPLEMENTALPUNCTUATION");
        public static final UnicodeBlock CJK_STROKES =
            new UnicodeBlock("CJK_STROKES",
                             "CJK STROKES",
                             "CJKSTROKES");
        public static final UnicodeBlock LISU =
            new UnicodeBlock("LISU");
        public static final UnicodeBlock VAI =
            new UnicodeBlock("VAI");
        public static final UnicodeBlock CYRILLIC_EXTENDED_B =
            new UnicodeBlock("CYRILLIC_EXTENDED_B",
                             "CYRILLIC EXTENDED-B",
                             "CYRILLICEXTENDED-B");
        public static final UnicodeBlock BAMUM =
            new UnicodeBlock("BAMUM");
        public static final UnicodeBlock MODIFIER_TONE_LETTERS =
            new UnicodeBlock("MODIFIER_TONE_LETTERS",
                             "MODIFIER TONE LETTERS",
                             "MODIFIERTONELETTERS");
        public static final UnicodeBlock LATIN_EXTENDED_D =
            new UnicodeBlock("LATIN_EXTENDED_D",
                             "LATIN EXTENDED-D",
                             "LATINEXTENDED-D");
        public static final UnicodeBlock SYLOTI_NAGRI =
            new UnicodeBlock("SYLOTI_NAGRI",
                             "SYLOTI NAGRI",
                             "SYLOTINAGRI");
        public static final UnicodeBlock COMMON_INDIC_NUMBER_FORMS =
            new UnicodeBlock("COMMON_INDIC_NUMBER_FORMS",
                             "COMMON INDIC NUMBER FORMS",
                             "COMMONINDICNUMBERFORMS");
        public static final UnicodeBlock PHAGS_PA =
            new UnicodeBlock("PHAGS_PA",
                             "PHAGS-PA");
        public static final UnicodeBlock SAURASHTRA =
            new UnicodeBlock("SAURASHTRA");
        public static final UnicodeBlock DEVANAGARI_EXTENDED =
            new UnicodeBlock("DEVANAGARI_EXTENDED",
                             "DEVANAGARI EXTENDED",
                             "DEVANAGARIEXTENDED");
        public static final UnicodeBlock KAYAH_LI =
            new UnicodeBlock("KAYAH_LI",
                             "KAYAH LI",
                             "KAYAHLI");
        public static final UnicodeBlock REJANG =
            new UnicodeBlock("REJANG");
        public static final UnicodeBlock HANGUL_JAMO_EXTENDED_A =
            new UnicodeBlock("HANGUL_JAMO_EXTENDED_A",
                             "HANGUL JAMO EXTENDED-A",
                             "HANGULJAMOEXTENDED-A");
        public static final UnicodeBlock JAVANESE =
            new UnicodeBlock("JAVANESE");
        public static final UnicodeBlock CHAM =
            new UnicodeBlock("CHAM");
        public static final UnicodeBlock MYANMAR_EXTENDED_A =
            new UnicodeBlock("MYANMAR_EXTENDED_A",
                             "MYANMAR EXTENDED-A",
                             "MYANMAREXTENDED-A");
        public static final UnicodeBlock TAI_VIET =
            new UnicodeBlock("TAI_VIET",
                             "TAI VIET",
                             "TAIVIET");
        public static final UnicodeBlock ETHIOPIC_EXTENDED_A =
            new UnicodeBlock("ETHIOPIC_EXTENDED_A",
                             "ETHIOPIC EXTENDED-A",
                             "ETHIOPICEXTENDED-A");
        public static final UnicodeBlock MEETEI_MAYEK =
            new UnicodeBlock("MEETEI_MAYEK",
                             "MEETEI MAYEK",
                             "MEETEIMAYEK");
        public static final UnicodeBlock HANGUL_JAMO_EXTENDED_B =
            new UnicodeBlock("HANGUL_JAMO_EXTENDED_B",
                             "HANGUL JAMO EXTENDED-B",
                             "HANGULJAMOEXTENDED-B");
        public static final UnicodeBlock VERTICAL_FORMS =
            new UnicodeBlock("VERTICAL_FORMS",
                             "VERTICAL FORMS",
                             "VERTICALFORMS");
        public static final UnicodeBlock ANCIENT_GREEK_NUMBERS =
            new UnicodeBlock("ANCIENT_GREEK_NUMBERS",
                             "ANCIENT GREEK NUMBERS",
                             "ANCIENTGREEKNUMBERS");
        public static final UnicodeBlock ANCIENT_SYMBOLS =
            new UnicodeBlock("ANCIENT_SYMBOLS",
                             "ANCIENT SYMBOLS",
                             "ANCIENTSYMBOLS");
        public static final UnicodeBlock PHAISTOS_DISC =
            new UnicodeBlock("PHAISTOS_DISC",
                             "PHAISTOS DISC",
                             "PHAISTOSDISC");
        public static final UnicodeBlock LYCIAN =
            new UnicodeBlock("LYCIAN");
        public static final UnicodeBlock CARIAN =
            new UnicodeBlock("CARIAN");
        public static final UnicodeBlock OLD_PERSIAN =
            new UnicodeBlock("OLD_PERSIAN",
                             "OLD PERSIAN",
                             "OLDPERSIAN");
        public static final UnicodeBlock IMPERIAL_ARAMAIC =
            new UnicodeBlock("IMPERIAL_ARAMAIC",
                             "IMPERIAL ARAMAIC",
                             "IMPERIALARAMAIC");
        public static final UnicodeBlock PHOENICIAN =
            new UnicodeBlock("PHOENICIAN");
        public static final UnicodeBlock LYDIAN =
            new UnicodeBlock("LYDIAN");
        public static final UnicodeBlock KHAROSHTHI =
            new UnicodeBlock("KHAROSHTHI");
        public static final UnicodeBlock OLD_SOUTH_ARABIAN =
            new UnicodeBlock("OLD_SOUTH_ARABIAN",
                             "OLD SOUTH ARABIAN",
                             "OLDSOUTHARABIAN");
        public static final UnicodeBlock AVESTAN =
            new UnicodeBlock("AVESTAN");
        public static final UnicodeBlock INSCRIPTIONAL_PARTHIAN =
            new UnicodeBlock("INSCRIPTIONAL_PARTHIAN",
                             "INSCRIPTIONAL PARTHIAN",
                             "INSCRIPTIONALPARTHIAN");
        public static final UnicodeBlock INSCRIPTIONAL_PAHLAVI =
            new UnicodeBlock("INSCRIPTIONAL_PAHLAVI",
                             "INSCRIPTIONAL PAHLAVI",
                             "INSCRIPTIONALPAHLAVI");
        public static final UnicodeBlock OLD_TURKIC =
            new UnicodeBlock("OLD_TURKIC",
                             "OLD TURKIC",
                             "OLDTURKIC");
        public static final UnicodeBlock RUMI_NUMERAL_SYMBOLS =
            new UnicodeBlock("RUMI_NUMERAL_SYMBOLS",
                             "RUMI NUMERAL SYMBOLS",
                             "RUMINUMERALSYMBOLS");
        public static final UnicodeBlock BRAHMI =
            new UnicodeBlock("BRAHMI");
        public static final UnicodeBlock KAITHI =
            new UnicodeBlock("KAITHI");
        public static final UnicodeBlock CUNEIFORM =
            new UnicodeBlock("CUNEIFORM");
        public static final UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION =
            new UnicodeBlock("CUNEIFORM_NUMBERS_AND_PUNCTUATION",
                             "CUNEIFORM NUMBERS AND PUNCTUATION",
                             "CUNEIFORMNUMBERSANDPUNCTUATION");
        public static final UnicodeBlock EGYPTIAN_HIEROGLYPHS =
            new UnicodeBlock("EGYPTIAN_HIEROGLYPHS",
                             "EGYPTIAN HIEROGLYPHS",
                             "EGYPTIANHIEROGLYPHS");
        public static final UnicodeBlock BAMUM_SUPPLEMENT =
            new UnicodeBlock("BAMUM_SUPPLEMENT",
                             "BAMUM SUPPLEMENT",
                             "BAMUMSUPPLEMENT");
        public static final UnicodeBlock KANA_SUPPLEMENT =
            new UnicodeBlock("KANA_SUPPLEMENT",
                             "KANA SUPPLEMENT",
                             "KANASUPPLEMENT");
        public static final UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION =
            new UnicodeBlock("ANCIENT_GREEK_MUSICAL_NOTATION",
                             "ANCIENT GREEK MUSICAL NOTATION",
                             "ANCIENTGREEKMUSICALNOTATION");
        public static final UnicodeBlock COUNTING_ROD_NUMERALS =
            new UnicodeBlock("COUNTING_ROD_NUMERALS",
                             "COUNTING ROD NUMERALS",
                             "COUNTINGRODNUMERALS");
        public static final UnicodeBlock MAHJONG_TILES =
            new UnicodeBlock("MAHJONG_TILES",
                             "MAHJONG TILES",
                             "MAHJONGTILES");
        public static final UnicodeBlock DOMINO_TILES =
            new UnicodeBlock("DOMINO_TILES",
                             "DOMINO TILES",
                             "DOMINOTILES");
        public static final UnicodeBlock PLAYING_CARDS =
            new UnicodeBlock("PLAYING_CARDS",
                             "PLAYING CARDS",
                             "PLAYINGCARDS");
        public static final UnicodeBlock ENCLOSED_ALPHANUMERIC_SUPPLEMENT =
            new UnicodeBlock("ENCLOSED_ALPHANUMERIC_SUPPLEMENT",
                             "ENCLOSED ALPHANUMERIC SUPPLEMENT",
                             "ENCLOSEDALPHANUMERICSUPPLEMENT");
        public static final UnicodeBlock ENCLOSED_IDEOGRAPHIC_SUPPLEMENT =
            new UnicodeBlock("ENCLOSED_IDEOGRAPHIC_SUPPLEMENT",
                             "ENCLOSED IDEOGRAPHIC SUPPLEMENT",
                             "ENCLOSEDIDEOGRAPHICSUPPLEMENT");
        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS =
            new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS",
                             "MISCELLANEOUS SYMBOLS AND PICTOGRAPHS",
                             "MISCELLANEOUSSYMBOLSANDPICTOGRAPHS");
        public static final UnicodeBlock EMOTICONS =
            new UnicodeBlock("EMOTICONS");
        public static final UnicodeBlock TRANSPORT_AND_MAP_SYMBOLS =
            new UnicodeBlock("TRANSPORT_AND_MAP_SYMBOLS",
                             "TRANSPORT AND MAP SYMBOLS",
                             "TRANSPORTANDMAPSYMBOLS");
        public static final UnicodeBlock ALCHEMICAL_SYMBOLS =
            new UnicodeBlock("ALCHEMICAL_SYMBOLS",
                             "ALCHEMICAL SYMBOLS",
                             "ALCHEMICALSYMBOLS");
        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C =
            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C",
                             "CJK UNIFIED IDEOGRAPHS EXTENSION C",
                             "CJKUNIFIEDIDEOGRAPHSEXTENSIONC");
        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D =
            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D",
                             "CJK UNIFIED IDEOGRAPHS EXTENSION D",
                             "CJKUNIFIEDIDEOGRAPHSEXTENSIOND");
        public static final UnicodeBlock ARABIC_EXTENDED_A =
            new UnicodeBlock("ARABIC_EXTENDED_A",
                             "ARABIC EXTENDED-A",
                             "ARABICEXTENDED-A");
        public static final UnicodeBlock SUNDANESE_SUPPLEMENT =
            new UnicodeBlock("SUNDANESE_SUPPLEMENT",
                             "SUNDANESE SUPPLEMENT",
                             "SUNDANESESUPPLEMENT");
        public static final UnicodeBlock MEETEI_MAYEK_EXTENSIONS =
            new UnicodeBlock("MEETEI_MAYEK_EXTENSIONS",
                             "MEETEI MAYEK EXTENSIONS",
                             "MEETEIMAYEKEXTENSIONS");
        public static final UnicodeBlock MEROITIC_HIEROGLYPHS =
            new UnicodeBlock("MEROITIC_HIEROGLYPHS",
                             "MEROITIC HIEROGLYPHS",
                             "MEROITICHIEROGLYPHS");
        public static final UnicodeBlock MEROITIC_CURSIVE =
            new UnicodeBlock("MEROITIC_CURSIVE",
                             "MEROITIC CURSIVE",
                             "MEROITICCURSIVE");
        public static final UnicodeBlock SORA_SOMPENG =
            new UnicodeBlock("SORA_SOMPENG",
                             "SORA SOMPENG",
                             "SORASOMPENG");
        public static final UnicodeBlock CHAKMA =
            new UnicodeBlock("CHAKMA");
        public static final UnicodeBlock SHARADA =
            new UnicodeBlock("SHARADA");
        public static final UnicodeBlock TAKRI =
            new UnicodeBlock("TAKRI");
        public static final UnicodeBlock MIAO =
            new UnicodeBlock("MIAO");
        public static final UnicodeBlock ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS =
            new UnicodeBlock("ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS",
                             "ARABIC MATHEMATICAL ALPHABETIC SYMBOLS",
                             "ARABICMATHEMATICALALPHABETICSYMBOLS");
        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS_EXTENDED =
            new UnicodeBlock("COMBINING_DIACRITICAL_MARKS_EXTENDED",
                             "COMBINING DIACRITICAL MARKS EXTENDED",
                             "COMBININGDIACRITICALMARKSEXTENDED");
        public static final UnicodeBlock MYANMAR_EXTENDED_B =
            new UnicodeBlock("MYANMAR_EXTENDED_B",
                             "MYANMAR EXTENDED-B",
                             "MYANMAREXTENDED-B");
        public static final UnicodeBlock LATIN_EXTENDED_E =
            new UnicodeBlock("LATIN_EXTENDED_E",
                             "LATIN EXTENDED-E",
                             "LATINEXTENDED-E");
        public static final UnicodeBlock COPTIC_EPACT_NUMBERS =
            new UnicodeBlock("COPTIC_EPACT_NUMBERS",
                             "COPTIC EPACT NUMBERS",
                             "COPTICEPACTNUMBERS");
        public static final UnicodeBlock OLD_PERMIC =
            new UnicodeBlock("OLD_PERMIC",
                             "OLD PERMIC",
                             "OLDPERMIC");
        public static final UnicodeBlock ELBASAN =
            new UnicodeBlock("ELBASAN");
        public static final UnicodeBlock CAUCASIAN_ALBANIAN =
            new UnicodeBlock("CAUCASIAN_ALBANIAN",
                             "CAUCASIAN ALBANIAN",
                             "CAUCASIANALBANIAN");
        public static final UnicodeBlock LINEAR_A =
            new UnicodeBlock("LINEAR_A",
                             "LINEAR A",
                             "LINEARA");
        public static final UnicodeBlock PALMYRENE =
            new UnicodeBlock("PALMYRENE");
        public static final UnicodeBlock NABATAEAN =
            new UnicodeBlock("NABATAEAN");
        public static final UnicodeBlock OLD_NORTH_ARABIAN =
            new UnicodeBlock("OLD_NORTH_ARABIAN",
                             "OLD NORTH ARABIAN",
                             "OLDNORTHARABIAN");
        public static final UnicodeBlock MANICHAEAN =
            new UnicodeBlock("MANICHAEAN");
        public static final UnicodeBlock PSALTER_PAHLAVI =
            new UnicodeBlock("PSALTER_PAHLAVI",
                             "PSALTER PAHLAVI",
                             "PSALTERPAHLAVI");
        public static final UnicodeBlock MAHAJANI =
            new UnicodeBlock("MAHAJANI");
        public static final UnicodeBlock SINHALA_ARCHAIC_NUMBERS =
            new UnicodeBlock("SINHALA_ARCHAIC_NUMBERS",
                             "SINHALA ARCHAIC NUMBERS",
                             "SINHALAARCHAICNUMBERS");
        public static final UnicodeBlock KHOJKI =
            new UnicodeBlock("KHOJKI");
        public static final UnicodeBlock KHUDAWADI =
            new UnicodeBlock("KHUDAWADI");
        public static final UnicodeBlock GRANTHA =
            new UnicodeBlock("GRANTHA");
        public static final UnicodeBlock TIRHUTA =
            new UnicodeBlock("TIRHUTA");
        public static final UnicodeBlock SIDDHAM =
            new UnicodeBlock("SIDDHAM");
        public static final UnicodeBlock MODI =
            new UnicodeBlock("MODI");
        public static final UnicodeBlock WARANG_CITI =
            new UnicodeBlock("WARANG_CITI",
                             "WARANG CITI",
                             "WARANGCITI");
        public static final UnicodeBlock PAU_CIN_HAU =
            new UnicodeBlock("PAU_CIN_HAU",
                             "PAU CIN HAU",
                             "PAUCINHAU");
        public static final UnicodeBlock MRO =
            new UnicodeBlock("MRO");
        public static final UnicodeBlock BASSA_VAH =
            new UnicodeBlock("BASSA_VAH",
                             "BASSA VAH",
                             "BASSAVAH");
        public static final UnicodeBlock PAHAWH_HMONG =
            new UnicodeBlock("PAHAWH_HMONG",
                             "PAHAWH HMONG",
                             "PAHAWHHMONG");
        public static final UnicodeBlock DUPLOYAN =
            new UnicodeBlock("DUPLOYAN");
        public static final UnicodeBlock SHORTHAND_FORMAT_CONTROLS =
            new UnicodeBlock("SHORTHAND_FORMAT_CONTROLS",
                             "SHORTHAND FORMAT CONTROLS",
                             "SHORTHANDFORMATCONTROLS");
        public static final UnicodeBlock MENDE_KIKAKUI =
            new UnicodeBlock("MENDE_KIKAKUI",
                             "MENDE KIKAKUI",
                             "MENDEKIKAKUI");
        public static final UnicodeBlock ORNAMENTAL_DINGBATS =
            new UnicodeBlock("ORNAMENTAL_DINGBATS",
                             "ORNAMENTAL DINGBATS",
                             "ORNAMENTALDINGBATS");
        public static final UnicodeBlock GEOMETRIC_SHAPES_EXTENDED =
            new UnicodeBlock("GEOMETRIC_SHAPES_EXTENDED",
                             "GEOMETRIC SHAPES EXTENDED",
                             "GEOMETRICSHAPESEXTENDED");
        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_C =
            new UnicodeBlock("SUPPLEMENTAL_ARROWS_C",
                             "SUPPLEMENTAL ARROWS-C",
                             "SUPPLEMENTALARROWS-C");
        public static final UnicodeBlock CHEROKEE_SUPPLEMENT =
            new UnicodeBlock("CHEROKEE_SUPPLEMENT",
                             "CHEROKEE SUPPLEMENT",
                             "CHEROKEESUPPLEMENT");
        public static final UnicodeBlock HATRAN =
            new UnicodeBlock("HATRAN");
        public static final UnicodeBlock OLD_HUNGARIAN =
            new UnicodeBlock("OLD_HUNGARIAN",
                             "OLD HUNGARIAN",
                             "OLDHUNGARIAN");
        public static final UnicodeBlock MULTANI =
            new UnicodeBlock("MULTANI");
        public static final UnicodeBlock AHOM =
            new UnicodeBlock("AHOM");
        public static final UnicodeBlock EARLY_DYNASTIC_CUNEIFORM =
            new UnicodeBlock("EARLY_DYNASTIC_CUNEIFORM",
                             "EARLY DYNASTIC CUNEIFORM",
                             "EARLYDYNASTICCUNEIFORM");
        public static final UnicodeBlock ANATOLIAN_HIEROGLYPHS =
            new UnicodeBlock("ANATOLIAN_HIEROGLYPHS",
                             "ANATOLIAN HIEROGLYPHS",
                             "ANATOLIANHIEROGLYPHS");
        public static final UnicodeBlock SUTTON_SIGNWRITING =
            new UnicodeBlock("SUTTON_SIGNWRITING",
                             "SUTTON SIGNWRITING",
                             "SUTTONSIGNWRITING");
        public static final UnicodeBlock SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS =
            new UnicodeBlock("SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS",
                             "SUPPLEMENTAL SYMBOLS AND PICTOGRAPHS",
                             "SUPPLEMENTALSYMBOLSANDPICTOGRAPHS");
        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E =
            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E",
                             "CJK UNIFIED IDEOGRAPHS EXTENSION E",
                             "CJKUNIFIEDIDEOGRAPHSEXTENSIONE");
        public static final UnicodeBlock SYRIAC_SUPPLEMENT =
            new UnicodeBlock("SYRIAC_SUPPLEMENT",
                             "SYRIAC SUPPLEMENT",
                             "SYRIACSUPPLEMENT");
        public static final UnicodeBlock CYRILLIC_EXTENDED_C =
            new UnicodeBlock("CYRILLIC_EXTENDED_C",
                             "CYRILLIC EXTENDED-C",
                             "CYRILLICEXTENDED-C");
        public static final UnicodeBlock OSAGE =
            new UnicodeBlock("OSAGE");
        public static final UnicodeBlock NEWA =
            new UnicodeBlock("NEWA");
        public static final UnicodeBlock MONGOLIAN_SUPPLEMENT =
            new UnicodeBlock("MONGOLIAN_SUPPLEMENT",
                             "MONGOLIAN SUPPLEMENT",
                             "MONGOLIANSUPPLEMENT");
        public static final UnicodeBlock MARCHEN =
            new UnicodeBlock("MARCHEN");
        public static final UnicodeBlock IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION =
            new UnicodeBlock("IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION",
                             "IDEOGRAPHIC SYMBOLS AND PUNCTUATION",
                             "IDEOGRAPHICSYMBOLSANDPUNCTUATION");
        public static final UnicodeBlock TANGUT =
            new UnicodeBlock("TANGUT");
        public static final UnicodeBlock TANGUT_COMPONENTS =
            new UnicodeBlock("TANGUT_COMPONENTS",
                             "TANGUT COMPONENTS",
                             "TANGUTCOMPONENTS");
        public static final UnicodeBlock KANA_EXTENDED_A =
            new UnicodeBlock("KANA_EXTENDED_A",
                             "KANA EXTENDED-A",
                             "KANAEXTENDED-A");
        public static final UnicodeBlock GLAGOLITIC_SUPPLEMENT =
            new UnicodeBlock("GLAGOLITIC_SUPPLEMENT",
                             "GLAGOLITIC SUPPLEMENT",
                             "GLAGOLITICSUPPLEMENT");
        public static final UnicodeBlock ADLAM =
            new UnicodeBlock("ADLAM");
        public static final UnicodeBlock MASARAM_GONDI =
            new UnicodeBlock("MASARAM_GONDI",
                             "MASARAM GONDI",
                             "MASARAMGONDI");
        public static final UnicodeBlock ZANABAZAR_SQUARE =
            new UnicodeBlock("ZANABAZAR_SQUARE",
                             "ZANABAZAR SQUARE",
                             "ZANABAZARSQUARE");
        public static final UnicodeBlock NUSHU =
            new UnicodeBlock("NUSHU");
        public static final UnicodeBlock SOYOMBO =
            new UnicodeBlock("SOYOMBO");
        public static final UnicodeBlock BHAIKSUKI =
            new UnicodeBlock("BHAIKSUKI");
        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F =
            new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F",
                             "CJK UNIFIED IDEOGRAPHS EXTENSION F",
                             "CJKUNIFIEDIDEOGRAPHSEXTENSIONF");
        public static final UnicodeBlock GEORGIAN_EXTENDED =
            new UnicodeBlock("GEORGIAN_EXTENDED",
                             "GEORGIAN EXTENDED",
                             "GEORGIANEXTENDED");
        public static final UnicodeBlock HANIFI_ROHINGYA =
            new UnicodeBlock("HANIFI_ROHINGYA",
                             "HANIFI ROHINGYA",
                             "HANIFIROHINGYA");
        public static final UnicodeBlock OLD_SOGDIAN =
            new UnicodeBlock("OLD_SOGDIAN",
                             "OLD SOGDIAN",
                             "OLDSOGDIAN");
        public static final UnicodeBlock SOGDIAN =
            new UnicodeBlock("SOGDIAN");
        public static final UnicodeBlock DOGRA =
            new UnicodeBlock("DOGRA");
        public static final UnicodeBlock GUNJALA_GONDI =
            new UnicodeBlock("GUNJALA_GONDI",
                             "GUNJALA GONDI",
                             "GUNJALAGONDI");
        public static final UnicodeBlock MAKASAR =
            new UnicodeBlock("MAKASAR");
        public static final UnicodeBlock MEDEFAIDRIN =
            new UnicodeBlock("MEDEFAIDRIN");
        public static final UnicodeBlock MAYAN_NUMERALS =
            new UnicodeBlock("MAYAN_NUMERALS",
                             "MAYAN NUMERALS",
                             "MAYANNUMERALS");
        public static final UnicodeBlock INDIC_SIYAQ_NUMBERS =
            new UnicodeBlock("INDIC_SIYAQ_NUMBERS",
                             "INDIC SIYAQ NUMBERS",
                             "INDICSIYAQNUMBERS");
        public static final UnicodeBlock CHESS_SYMBOLS =
            new UnicodeBlock("CHESS_SYMBOLS",
                             "CHESS SYMBOLS",
                             "CHESSSYMBOLS");
        private static final int blockStarts[] = {
            0x0000,   // 0000..007F; Basic Latin
            0x0080,   // 0080..00FF; Latin-1 Supplement
            0x0100,   // 0100..017F; Latin Extended-A
            // 途中省略
            0xA980,   // A980..A9DF; Javanese
            // 途中省略
            0xFE30,   // FE30..FE4F; CJK Compatibility Forms
            // 途中省略
            0x2A700,  // 2A700..2B73F; CJK Unified Ideographs Extension C
            0x2B740,  // 2B740..2B81F; CJK Unified Ideographs Extension D
            0x2B820,  // 2B820..2CEAF; CJK Unified Ideographs Extension E
            0x2CEB0,  // 2CEB0..2EBEF; CJK Unified Ideographs Extension F
            0x2EBF0,  //               unassigned
            0x2F800,  // 2F800..2FA1F; CJK Compatibility Ideographs Supplement
            0x2FA20,  //               unassigned
        };
        private static final UnicodeBlock[] blocks = {
            BASIC_LATIN,
            LATIN_1_SUPPLEMENT,
            LATIN_EXTENDED_A,
            LATIN_EXTENDED_B,
            IPA_EXTENSIONS,
            // 途中省略
            KANBUN,
            BOPOMOFO_EXTENDED,
            CJK_STROKES,
            KATAKANA_PHONETIC_EXTENSIONS,
            ENCLOSED_CJK_LETTERS_AND_MONTHS,
            CJK_COMPATIBILITY,
            CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A,
            YIJING_HEXAGRAM_SYMBOLS,
            CJK_UNIFIED_IDEOGRAPHS,
            YI_SYLLABLES,
            YI_RADICALS,
            // 途中省略
            HANGUL_JAMO_EXTENDED_A,
            JAVANESE,
            MYANMAR_EXTENDED_B,
            CHAM,
            MYANMAR_EXTENDED_A,
            // 途中省略
            KANA_SUPPLEMENT,
            KANA_EXTENDED_A,
            null,
            // 途中省略
            SUPPLEMENTARY_PRIVATE_USE_AREA_A,
            SUPPLEMENTARY_PRIVATE_USE_AREA_B
        };
        public static UnicodeBlock of(char c) {
            return of((int)c);
        }
        public static UnicodeBlock of(int codePoint) {
            if (!isValidCodePoint(codePoint)) {
                throw new IllegalArgumentException(
                    String.format("Not a valid Unicode code point: 0x%X", codePoint));
            }
            int top, bottom, current;
            bottom = 0;
            top = blockStarts.length;
            current = top/2;
            // invariant: top > current >= bottom && codePoint >= unicodeBlockStarts[bottom]
            while (top – bottom > 1) {
                if (codePoint >= blockStarts[current]) {
                    bottom = current;
                } else {
                    top = current;
                }
                current = (top + bottom) / 2;
            }
            return blocks[current];
        }
        public static final UnicodeBlock forName(String blockName) {
            UnicodeBlock block = map.get(blockName.toUpperCase(Locale.US));
            if (block == null) {
                throw new IllegalArgumentException("Not a valid block name: "
                            + blockName);
            }
            return block;
        }
    }
    public static enum UnicodeScript {
        COMMON,
        LATIN,
        GREEK,
        // 途中省略
        MEDEFAIDRIN,
        UNKNOWN;
        private static final int[] scriptStarts = {
            0x0000,   // 0000..0040; COMMON
            0x0041,   // 0041..005A; LATIN
            0x005B,   // 005B..0060; COMMON
            // 途中省略
            0xE0100,  // E0100..E01EF; INHERITED
            0xE01F0   // E01F0..10FFFF; UNKNOWN
        };
        private static final UnicodeScript[] scripts = {
            COMMON,                   // 0000..0040
            LATIN,                    // 0041..005A
            // 途中省略
            UNKNOWN                   // E01F0..10FFFF
        };
        private static HashMap<String, Character.UnicodeScript> aliases;
        static {
            aliases = new HashMap<>((int)(149 / 0.75f + 1.0f));
            aliases.put("ADLM", ADLAM);
            aliases.put("AGHB", CAUCASIAN_ALBANIAN);
            // 途中省略
            aliases.put("JAVA", JAVANESE);
            aliases.put("KALI", KAYAH_LI);
            // 途中省略
            aliases.put("ZINH", INHERITED);
            aliases.put("ZYYY", COMMON);
            aliases.put("ZZZZ", UNKNOWN);
        }
        public static UnicodeScript of(int codePoint) {
            if (!isValidCodePoint(codePoint))
                throw new IllegalArgumentException(
                    String.format("Not a valid Unicode code point: 0x%X", codePoint));
            int type = getType(codePoint);
            // leave SURROGATE and PRIVATE_USE for table lookup
            if (type == UNASSIGNED)
                return UNKNOWN;
            int index = Arrays.binarySearch(scriptStarts, codePoint);
            if (index < 0)
                index = -index – 2;
            return scripts[index];
        }
        public static final UnicodeScript forName(String scriptName) {
            scriptName = scriptName.toUpperCase(Locale.ENGLISH);
                                 //.replace(' ', '_'));
            UnicodeScript sc = aliases.get(scriptName);
            if (sc != null)
                return sc;
            return valueOf(scriptName);
        }
    }
    private final char value;
    private static final long serialVersionUID = 3786198910865385080L;
    @Deprecated(since="9")
    public Character(char value) {
        this.value = value;
    }
    private static class CharacterCache {
        private CharacterCache(){}
        static final Character[] cache;
        static Character[] archivedCache;
        static {
            int size = 127 + 1;
            // Load and use the archived cache if it exists
            VM.initializeFromArchive(CharacterCache.class);
            if (archivedCache == null || archivedCache.length != size) {
                Character[] c = new Character[size];
                for (int i = 0; i < size; i++) {
                    c[i] = new Character((char) i);
                }
                archivedCache = c;
            }
            cache = archivedCache;
        }
    }
    @HotSpotIntrinsicCandidate
    public static Character valueOf(char c) {
        if (c <= 127) { // must cache
            return CharacterCache.cache[(int)c];
        }
        return new Character(c);
    }
    @HotSpotIntrinsicCandidate
    public char charValue() {
        return value;
    }
    @Override
    public int hashCode() {
        return Character.hashCode(value);
    }
    public static int hashCode(char value) {
        return (int)value;
    }
    public boolean equals(Object obj) {
        if (obj instanceof Character) {
            return value == ((Character)obj).charValue();
        }
        return false;
    }
    public String toString() {
        char buf[] = {value};
        return String.valueOf(buf);
    }
    public static String toString(char c) {
        return String.valueOf(c);
    }
    public static String toString(int codePoint) {
        return String.valueOfCodePoint(codePoint);
    }
    public static boolean isValidCodePoint(int codePoint) {
        // Optimized form of:
        //     codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
        int plane = codePoint >>> 16;
        return plane < ((MAX_CODE_POINT + 1) >>> 16);
    }
    public static boolean isBmpCodePoint(int codePoint) {
        return codePoint >>> 16 == 0;
        // Optimized form of:
        //     codePoint >= MIN_VALUE && codePoint <= MAX_VALUE
        // We consistently use logical shift (>>>) to facilitate
        // additional runtime optimizations.
    }
    public static boolean isSupplementaryCodePoint(int codePoint) {
        return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT
            && codePoint <  MAX_CODE_POINT + 1;
    }
    public static boolean isHighSurrogate(char ch) {
        // Help VM constant-fold; MAX_HIGH_SURROGATE + 1 == MIN_LOW_SURROGATE
        return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1);
    }
    public static boolean isLowSurrogate(char ch) {
        return ch >= MIN_LOW_SURROGATE && ch < (MAX_LOW_SURROGATE + 1);
    }
    public static boolean isSurrogate(char ch) {
        return ch >= MIN_SURROGATE && ch < (MAX_SURROGATE + 1);
    }
    public static boolean isSurrogatePair(char high, char low) {
        return isHighSurrogate(high) && isLowSurrogate(low);
    }
    public static int charCount(int codePoint) {
        return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT ? 2 : 1;
    }
    public static int toCodePoint(char high, char low) {
        // Optimized form of:
        // return ((high – MIN_HIGH_SURROGATE) << 10)
        //         + (low – MIN_LOW_SURROGATE)
        //         + MIN_SUPPLEMENTARY_CODE_POINT;
        return ((high << 10) + low) + (MIN_SUPPLEMENTARY_CODE_POINT
                                       – (MIN_HIGH_SURROGATE << 10)
                                       – MIN_LOW_SURROGATE);
    }
    public static int codePointAt(CharSequence seq, int index) {
        char c1 = seq.charAt(index);
        if (isHighSurrogate(c1) && ++index < seq.length()) {
            char c2 = seq.charAt(index);
            if (isLowSurrogate(c2)) {
                return toCodePoint(c1, c2);
            }
        }
        return c1;
    }
    public static int codePointAt(char[] a, int index) {
        return codePointAtImpl(a, index, a.length);
    }
    public static int codePointAt(char[] a, int index, int limit) {
        if (index >= limit || limit < 0 || limit > a.length) {
            throw new IndexOutOfBoundsException();
        }
        return codePointAtImpl(a, index, limit);
    }
    // throws ArrayIndexOutOfBoundsException if index out of bounds
    static int codePointAtImpl(char[] a, int index, int limit) {
        char c1 = a[index];
        if (isHighSurrogate(c1) && ++index < limit) {
            char c2 = a[index];
            if (isLowSurrogate(c2)) {
                return toCodePoint(c1, c2);
            }
        }
        return c1;
    }
    public static int codePointBefore(CharSequence seq, int index) {
        char c2 = seq.charAt(–index);
        if (isLowSurrogate(c2) && index > 0) {
            char c1 = seq.charAt(–index);
            if (isHighSurrogate(c1)) {
                return toCodePoint(c1, c2);
            }
        }
        return c2;
    }
    public static int codePointBefore(char[] a, int index) {
        return codePointBeforeImpl(a, index, 0);
    }
    public static int codePointBefore(char[] a, int index, int start) {
        if (index <= start || start < 0 || start >= a.length) {
            throw new IndexOutOfBoundsException();
        }
        return codePointBeforeImpl(a, index, start);
    }
    // throws ArrayIndexOutOfBoundsException if index-1 out of bounds
    static int codePointBeforeImpl(char[] a, int index, int start) {
        char c2 = a[–index];
        if (isLowSurrogate(c2) && index > start) {
            char c1 = a[–index];
            if (isHighSurrogate(c1)) {
                return toCodePoint(c1, c2);
            }
        }
        return c2;
    }
    public static char highSurrogate(int codePoint) {
        return (char) ((codePoint >>> 10)
            + (MIN_HIGH_SURROGATE – (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
    }
    public static char lowSurrogate(int codePoint) {
        return (char) ((codePoint & 0x3ff) + MIN_LOW_SURROGATE);
    }
    public static int toChars(int codePoint, char[] dst, int dstIndex) {
        if (isBmpCodePoint(codePoint)) {
            dst[dstIndex] = (char) codePoint;
            return 1;
        } else if (isValidCodePoint(codePoint)) {
            toSurrogates(codePoint, dst, dstIndex);
            return 2;
        } else {
            throw new IllegalArgumentException(
                String.format("Not a valid Unicode code point: 0x%X", codePoint));
        }
    }
    public static char[] toChars(int codePoint) {
        if (isBmpCodePoint(codePoint)) {
            return new char[] { (char) codePoint };
        } else if (isValidCodePoint(codePoint)) {
            char[] result = new char[2];
            toSurrogates(codePoint, result, 0);
            return result;
        } else {
            throw new IllegalArgumentException(
                String.format("Not a valid Unicode code point: 0x%X", codePoint));
        }
    }
    static void toSurrogates(int codePoint, char[] dst, int index) {
        // We write elements "backwards" to guarantee all-or-nothing
        dst[index+1] = lowSurrogate(codePoint);
        dst[index] = highSurrogate(codePoint);
    }
    public static int codePointCount(CharSequence seq, int beginIndex, int endIndex) {
        int length = seq.length();
        if (beginIndex < 0 || endIndex > length || beginIndex > endIndex) {
            throw new IndexOutOfBoundsException();
        }
        int n = endIndex – beginIndex;
        for (int i = beginIndex; i < endIndex; ) {
            if (isHighSurrogate(seq.charAt(i++)) && i < endIndex &&
                isLowSurrogate(seq.charAt(i))) {
                n–;
                i++;
            }
        }
        return n;
    }
    public static int codePointCount(char[] a, int offset, int count) {
        if (count > a.length – offset || offset < 0 || count < 0) {
            throw new IndexOutOfBoundsException();
        }
        return codePointCountImpl(a, offset, count);
    }
    static int codePointCountImpl(char[] a, int offset, int count) {
        int endIndex = offset + count;
        int n = count;
        for (int i = offset; i < endIndex; ) {
            if (isHighSurrogate(a[i++]) && i < endIndex &&
                isLowSurrogate(a[i])) {
                n–;
                i++;
            }
        }
        return n;
    }
    public static int offsetByCodePoints(CharSequence seq, int index,
                                         int codePointOffset) {
        int length = seq.length();
        if (index < 0 || index > length) {
            throw new IndexOutOfBoundsException();
        }
        int x = index;
        if (codePointOffset >= 0) {
            int i;
            for (i = 0; x < length && i < codePointOffset; i++) {
                if (isHighSurrogate(seq.charAt(x++)) && x < length &&
                    isLowSurrogate(seq.charAt(x))) {
                    x++;
                }
            }
            if (i < codePointOffset) {
                throw new IndexOutOfBoundsException();
            }
        } else {
            int i;
            for (i = codePointOffset; x > 0 && i < 0; i++) {
                if (isLowSurrogate(seq.charAt(–x)) && x > 0 &&
                    isHighSurrogate(seq.charAt(x-1))) {
                    x–;
                }
            }
            if (i < 0) {
                throw new IndexOutOfBoundsException();
            }
        }
        return x;
    }
    public static int offsetByCodePoints(char[] a, int start, int count,
                                         int index, int codePointOffset) {
        if (count > a.length-start || start < 0 || count < 0
            || index < start || index > start+count) {
            throw new IndexOutOfBoundsException();
        }
        return offsetByCodePointsImpl(a, start, count, index, codePointOffset);
    }
    static int offsetByCodePointsImpl(char[]a, int start, int count,
                                      int index, int codePointOffset) {
        int x = index;
        if (codePointOffset >= 0) {
            int limit = start + count;
            int i;
            for (i = 0; x < limit && i < codePointOffset; i++) {
                if (isHighSurrogate(a[x++]) && x < limit &&
                    isLowSurrogate(a[x])) {
                    x++;
                }
            }
            if (i < codePointOffset) {
                throw new IndexOutOfBoundsException();
            }
        } else {
            int i;
            for (i = codePointOffset; x > start && i < 0; i++) {
                if (isLowSurrogate(a[–x]) && x > start &&
                    isHighSurrogate(a[x-1])) {
                    x–;
                }
            }
            if (i < 0) {
                throw new IndexOutOfBoundsException();
            }
        }
        return x;
    }
    public static boolean isLowerCase(char ch) {
        return isLowerCase((int)ch);
    }
    public static boolean isLowerCase(int codePoint) {
        return CharacterData.of(codePoint).isLowerCase(codePoint) ||
               CharacterData.of(codePoint).isOtherLowercase(codePoint);
    }
    public static boolean isUpperCase(char ch) {
        return isUpperCase((int)ch);
    }
    public static boolean isUpperCase(int codePoint) {
        return CharacterData.of(codePoint).isUpperCase(codePoint) ||
               CharacterData.of(codePoint).isOtherUppercase(codePoint);
    }
    public static boolean isTitleCase(char ch) {
        return isTitleCase((int)ch);
    }
    public static boolean isTitleCase(int codePoint) {
        return getType(codePoint) == Character.TITLECASE_LETTER;
    }
    public static boolean isDigit(char ch) {
        return isDigit((int)ch);
    }
    public static boolean isDigit(int codePoint) {
        return CharacterData.of(codePoint).isDigit(codePoint);
    }
    public static boolean isDefined(char ch) {
        return isDefined((int)ch);
    }
    public static boolean isDefined(int codePoint) {
        return getType(codePoint) != Character.UNASSIGNED;
    }
    public static boolean isLetter(char ch) {
        return isLetter((int)ch);
    }
    public static boolean isLetter(int codePoint) {
        return ((((1 << Character.UPPERCASE_LETTER) |
            (1 << Character.LOWERCASE_LETTER) |
            (1 << Character.TITLECASE_LETTER) |
            (1 << Character.MODIFIER_LETTER) |
            (1 << Character.OTHER_LETTER)) >> getType(codePoint)) & 1)
            != 0;
    }
    public static boolean isLetterOrDigit(char ch) {
        return isLetterOrDigit((int)ch);
    }
    public static boolean isLetterOrDigit(int codePoint) {
        return ((((1 << Character.UPPERCASE_LETTER) |
            (1 << Character.LOWERCASE_LETTER) |
            (1 << Character.TITLECASE_LETTER) |
            (1 << Character.MODIFIER_LETTER) |
            (1 << Character.OTHER_LETTER) |
            (1 << Character.DECIMAL_DIGIT_NUMBER)) >> getType(codePoint)) & 1)
            != 0;
    }
    @Deprecated(since="1.1")
    public static boolean isJavaLetter(char ch) {
        return isJavaIdentifierStart(ch);
    }
    @Deprecated(since="1.1")
    public static boolean isJavaLetterOrDigit(char ch) {
        return isJavaIdentifierPart(ch);
    }
    public static boolean isAlphabetic(int codePoint) {
        return (((((1 << Character.UPPERCASE_LETTER) |
            (1 << Character.LOWERCASE_LETTER) |
            (1 << Character.TITLECASE_LETTER) |
            (1 << Character.MODIFIER_LETTER) |
            (1 << Character.OTHER_LETTER) |
            (1 << Character.LETTER_NUMBER)) >> getType(codePoint)) & 1) != 0) ||
            CharacterData.of(codePoint).isOtherAlphabetic(codePoint);
    }
    public static boolean isIdeographic(int codePoint) {
        return CharacterData.of(codePoint).isIdeographic(codePoint);
    }
    public static boolean isJavaIdentifierStart(char ch) {
        return isJavaIdentifierStart((int)ch);
    }
    public static boolean isJavaIdentifierStart(int codePoint) {
        return CharacterData.of(codePoint).isJavaIdentifierStart(codePoint);
    }
    public static boolean isJavaIdentifierPart(char ch) {
        return isJavaIdentifierPart((int)ch);
    }
    public static boolean isJavaIdentifierPart(int codePoint) {
        return CharacterData.of(codePoint).isJavaIdentifierPart(codePoint);
    }
    public static boolean isUnicodeIdentifierStart(char ch) {
        return isUnicodeIdentifierStart((int)ch);
    }
    public static boolean isUnicodeIdentifierStart(int codePoint) {
        return CharacterData.of(codePoint).isUnicodeIdentifierStart(codePoint);
    }
    public static boolean isUnicodeIdentifierPart(char ch) {
        return isUnicodeIdentifierPart((int)ch);
    }
    public static boolean isUnicodeIdentifierPart(int codePoint) {
        return CharacterData.of(codePoint).isUnicodeIdentifierPart(codePoint);
    }
    public static boolean isIdentifierIgnorable(char ch) {
        return isIdentifierIgnorable((int)ch);
    }
    public static boolean isIdentifierIgnorable(int codePoint) {
        return CharacterData.of(codePoint).isIdentifierIgnorable(codePoint);
    }
    public static char toLowerCase(char ch) {
        return (char)toLowerCase((int)ch);
    }
    public static int toLowerCase(int codePoint) {
        return CharacterData.of(codePoint).toLowerCase(codePoint);
    }
    public static char toUpperCase(char ch) {
        return (char)toUpperCase((int)ch);
    }
    public static int toUpperCase(int codePoint) {
        return CharacterData.of(codePoint).toUpperCase(codePoint);
    }
    public static char toTitleCase(char ch) {
        return (char)toTitleCase((int)ch);
    }
    public static int toTitleCase(int codePoint) {
        return CharacterData.of(codePoint).toTitleCase(codePoint);
    }
    public static int digit(char ch, int radix) {
        return digit((int)ch, radix);
    }
    public static int digit(int codePoint, int radix) {
        return CharacterData.of(codePoint).digit(codePoint, radix);
    }
    public static int getNumericValue(char ch) {
        return getNumericValue((int)ch);
    }
    public static int getNumericValue(int codePoint) {
        return CharacterData.of(codePoint).getNumericValue(codePoint);
    }
    @Deprecated(since="1.1")
    public static boolean isSpace(char ch) {
        return (ch <= 0x0020) &&
            (((((1L << 0x0009) |
            (1L << 0x000A) |
            (1L << 0x000C) |
            (1L << 0x000D) |
            (1L << 0x0020)) >> ch) & 1L) != 0);
    }
    public static boolean isSpaceChar(char ch) {
        return isSpaceChar((int)ch);
    }
    public static boolean isSpaceChar(int codePoint) {
        return ((((1 << Character.SPACE_SEPARATOR) |
                  (1 << Character.LINE_SEPARATOR) |
                  (1 << Character.PARAGRAPH_SEPARATOR)) >> getType(codePoint)) & 1)
            != 0;
    }
    public static boolean isWhitespace(char ch) {
        return isWhitespace((int)ch);
    }
    public static boolean isWhitespace(int codePoint) {
        return CharacterData.of(codePoint).isWhitespace(codePoint);
    }
    public static boolean isISOControl(char ch) {
        return isISOControl((int)ch);
    }
    public static boolean isISOControl(int codePoint) {
        // Optimized form of:
        //     (codePoint >= 0x00 && codePoint <= 0x1F) ||
        //     (codePoint >= 0x7F && codePoint <= 0x9F);
        return codePoint <= 0x9F &&
            (codePoint >= 0x7F || (codePoint >>> 5 == 0));
    }
    public static int getType(char ch) {
        return getType((int)ch);
    }
    public static int getType(int codePoint) {
        return CharacterData.of(codePoint).getType(codePoint);
    }
    public static char forDigit(int digit, int radix) {
        if ((digit >= radix) || (digit < 0)) {
            return '\0';
        }
        if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX)) {
            return '\0';
        }
        if (digit < 10) {
            return (char)('0' + digit);
        }
        return (char)('a' – 10 + digit);
    }
    public static byte getDirectionality(char ch) {
        return getDirectionality((int)ch);
    }
    public static byte getDirectionality(int codePoint) {
        return CharacterData.of(codePoint).getDirectionality(codePoint);
    }
    public static boolean isMirrored(char ch) {
        return isMirrored((int)ch);
    }
    public static boolean isMirrored(int codePoint) {
        return CharacterData.of(codePoint).isMirrored(codePoint);
    }
    public int compareTo(Character anotherCharacter) {
        return compare(this.value, anotherCharacter.value);
    }
    public static int compare(char x, char y) {
        return x – y;
    }
    static int toUpperCaseEx(int codePoint) {
        assert isValidCodePoint(codePoint);
        return CharacterData.of(codePoint).toUpperCaseEx(codePoint);
    }
    static char[] toUpperCaseCharArray(int codePoint) {
        // As of Unicode 6.0, 1:M uppercasings only happen in the BMP.
        assert isBmpCodePoint(codePoint);
        return CharacterData.of(codePoint).toUpperCaseCharArray(codePoint);
    }
    public static final int SIZE = 16;
    public static final int BYTES = SIZE / Byte.SIZE;
    @HotSpotIntrinsicCandidate
    public static char reverseBytes(char ch) {
        return (char) (((ch & 0xFF00) >> 8) | (ch << 8));
    }
    public static String getName(int codePoint) {
        if (!isValidCodePoint(codePoint)) {
            throw new IllegalArgumentException(
                String.format("Not a valid Unicode code point: 0x%X", codePoint));
        }
        String name = CharacterName.getInstance().getName(codePoint);
        if (name != null)
            return name;
        if (getType(codePoint) == UNASSIGNED)
            return null;
        UnicodeBlock block = UnicodeBlock.of(codePoint);
        if (block != null)
            return block.toString().replace('_', ' ') + " "
                   + Integer.toHexString(codePoint).toUpperCase(Locale.ROOT);
        // should never come here
        return Integer.toHexString(codePoint).toUpperCase(Locale.ROOT);
    }
    public static int codePointOf(String name) {
        name = name.trim().toUpperCase(Locale.ROOT);
        int cp = CharacterName.getInstance().getCodePoint(name);
        if (cp != -1)
            return cp;
        try {
            int off = name.lastIndexOf(' ');
            if (off != -1) {
                cp = Integer.parseInt(name, off + 1, name.length(), 16);
                if (isValidCodePoint(cp) && name.equals(getName(cp)))
                    return cp;
            }
        } catch (Exception x) {}
        throw new IllegalArgumentException("Unrecognized character name :" + name);
    }
}
JDK

java.lang.Numberクラスのソースコード

Number型はIntegerなどのプリミティブ型数値のラッパークラスのスーパークラスである。プリミティブ型を取得するためのintValue()メソッドなどは抽象メソッドとして宣言されている。byteValue()メソッドとshortValue()メソッドのみ実装されている。

/*
 * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;
public abstract class Number implements java.io.Serializable {
    public abstract int intValue();
    public abstract long longValue();
    public abstract float floatValue();
    public abstract double doubleValue();
    public byte byteValue() {
        return (byte)intValue();
    }
    public short shortValue() {
        return (short)intValue();
    }
    private static final long serialVersionUID = -8742448824652078965L;
}
JDK

java.lang.Enumクラスのソースコード

Enumクラスは抽象クラスであり,nameという文字列型のフィールドに名前を,ordinalというint型の変数に値を保持している。protectedのコンストラクタではこれらのフィールドを指定する必要がある。toString()メソッドではnameを返すようになっている。またcompreTo()メソッドは,ordinalフィールドを用いて大小判定を行う。

staticなvalueOfメソッドで,nameと一致するものがあればそのEnum値を返す。みつからない場合はIllegalArgumentExceptionをスローする。また引数がnullの場合はNullPointerExceptionがスローされる。

/*
 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.constant.ClassDesc;
import java.lang.constant.Constable;
import java.lang.constant.ConstantDescs;
import java.lang.constant.DynamicConstantDesc;
import java.lang.invoke.MethodHandles;
import java.util.Optional;
import static java.util.Objects.requireNonNull;
@SuppressWarnings("serial") // No serialVersionUID needed due to
                            // special-casing of enum types.
public abstract class Enum<E extends Enum<E>>
        implements Constable, Comparable<E>, Serializable {
    private final String name;
    public final String name() {
        return name;
    }
    private final int ordinal;
    public final int ordinal() {
        return ordinal;
    }
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
    public String toString() {
        return name;
    }
    public final boolean equals(Object other) {
        return this==other;
    }
    public final int hashCode() {
        return super.hashCode();
    }
    protected final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
    public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal – other.ordinal;
    }
    @SuppressWarnings("unchecked")
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }
    @Override
    public final Optional<EnumDesc<E>> describeConstable() {
        return getDeclaringClass()
                .describeConstable()
                .map(c -> EnumDesc.of(c, name));
    }
    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }
    @SuppressWarnings("deprecation")
    protected final void finalize() { }
    private void readObject(ObjectInputStream in) throws IOException,
        ClassNotFoundException {
        throw new InvalidObjectException("can't deserialize enum");
    }
    private void readObjectNoData() throws ObjectStreamException {
        throw new InvalidObjectException("can't deserialize enum");
    }
    public static final class EnumDesc<E extends Enum<E>>
            extends DynamicConstantDesc<E> {
        private EnumDesc(ClassDesc constantType, String constantName) {
            super(ConstantDescs.BSM_ENUM_CONSTANT, requireNonNull(constantName), requireNonNull(constantType));
        }
        public static<E extends Enum<E>> EnumDesc<E> of(ClassDesc enumClass,
                                                        String constantName) {
            return new EnumDesc<>(enumClass, constantName);
        }
        @Override
        @SuppressWarnings("unchecked")
        public E resolveConstantDesc(MethodHandles.Lookup lookup)
                throws ReflectiveOperationException {
            return Enum.valueOf((Class<E>) constantType().resolveConstantDesc(lookup), constantName());
        }
        @Override
        public String toString() {
            return String.format("EnumDesc[%s.%s]", constantType().displayName(), constantName());
        }
    }
}
JDK

java.lang.ProcessBuilderクラスのソースコード

Javaで外部プロセスを生成して実行するためのProcessを構築するProcessBuilderクラスのソースコードである。このクラスはfinalとして宣言されており,サブクラスを作成できない。

 コンストラクタは引数としてList<String>をとるものと,String…をとるものの2種類が定義されている。引数として与えられた文字列はList<String>型のインスタンス変数commandに格納されている。

command( List<String> )メソッドあるいは,command(String…)ではcommandのListに追加するよう実装されている。引数をとらないcommand()メソッドは,このインスタンス変数commandを返す。

environment()メソッドでは,権限チェックを行ったのち,ProcessEnvironmentクラスのstaticメソッドenvironment()を呼び出して,環境変数のキーと値のMapを返すようになっている。環境変数を設定するenvironment(String[] envp)メソッドでは,C言語タイプの文字列(0x00で終端する文字列)を扱えるよう,というNULL文字以降を空文字列に置換する処理が行われている。

if (envstring.indexOf((int) ‘\u0000’) != -1)
envstring = envstring.replaceFirst(“\u0000.*”, “”);

中段にはプロセスとやり取りするためのストリームを制御するメソッドが定義されている。

privateなstart(Redirect[] redirects)メソッドでは,引数のチェックを行った上で,ProcessImplクラスのstaticメソッドstart()を実行する。

/*
 * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import sun.security.action.GetPropertyAction;
public final class ProcessBuilder
{
    private List<String> command;
    private File directory;
    private Map<String,String> environment;
    private boolean redirectErrorStream;
    private Redirect[] redirects;
    public ProcessBuilder(List<String> command) {
        if (command == null)
            throw new NullPointerException();
        this.command = command;
    }
    public ProcessBuilder(String… command) {
        this.command = new ArrayList<>(command.length);
        for (String arg : command)
            this.command.add(arg);
    }
    public ProcessBuilder command(List<String> command) {
        if (command == null)
            throw new NullPointerException();
        this.command = command;
        return this;
    }
    public ProcessBuilder command(String… command) {
        this.command = new ArrayList<>(command.length);
        for (String arg : command)
            this.command.add(arg);
        return this;
    }
    public List<String> command() {
        return command;
    }
    public Map<String,String> environment() {
        SecurityManager security = System.getSecurityManager();
        if (security != null)
            security.checkPermission(new RuntimePermission("getenv.*"));
        if (environment == null)
            environment = ProcessEnvironment.environment();
        assert environment != null;
        return environment;
    }
    // Only for use by Runtime.exec(…envp…)
    ProcessBuilder environment(String[] envp) {
        assert environment == null;
        if (envp != null) {
            environment = ProcessEnvironment.emptyEnvironment(envp.length);
            assert environment != null;
            for (String envstring : envp) {
                // Before 1.5, we blindly passed invalid envstrings
                // to the child process.
                // We would like to throw an exception, but do not,
                // for compatibility with old broken code.
                // Silently discard any trailing junk.
                if (envstring.indexOf((int) '\u0000') != -1)
                    envstring = envstring.replaceFirst("\u0000.*", "");
                int eqlsign =
                    envstring.indexOf('=', ProcessEnvironment.MIN_NAME_LENGTH);
                // Silently ignore envstrings lacking the required `='.
                if (eqlsign != -1)
                    environment.put(envstring.substring(0,eqlsign),
                                    envstring.substring(eqlsign+1));
            }
        }
        return this;
    }
    public File directory() {
        return directory;
    }
    public ProcessBuilder directory(File directory) {
        this.directory = directory;
        return this;
    }
    // —————- I/O Redirection —————-
    static class NullInputStream extends InputStream {
        static final NullInputStream INSTANCE = new NullInputStream();
        private NullInputStream() {}
        public int read()      { return -1; }
        public int available() { return 0; }
    }
    static class NullOutputStream extends OutputStream {
        static final NullOutputStream INSTANCE = new NullOutputStream();
        private NullOutputStream() {}
        public void write(int b) throws IOException {
            throw new IOException("Stream closed");
        }
    }
    public abstract static class Redirect {
        private static final File NULL_FILE = new File(
                (GetPropertyAction.privilegedGetProperty("os.name")
                        .startsWith("Windows") ? "NUL" : "/dev/null")
        );
        public enum Type {
            PIPE,
            INHERIT,
            READ,
            WRITE,
            APPEND
        };
        public abstract Type type();
        public static final Redirect PIPE = new Redirect() {
                public Type type() { return Type.PIPE; }
                public String toString() { return type().toString(); }};
        public static final Redirect INHERIT = new Redirect() {
                public Type type() { return Type.INHERIT; }
                public String toString() { return type().toString(); }};
        public static final Redirect DISCARD = new Redirect() {
                public Type type() { return Type.WRITE; }
                public String toString() { return type().toString(); }
                public File file() { return NULL_FILE; }
                boolean append() { return false; }
        };
        public File file() { return null; }
        boolean append() {
            throw new UnsupportedOperationException();
        }
        public static Redirect from(final File file) {
            if (file == null)
                throw new NullPointerException();
            return new Redirect() {
                    public Type type() { return Type.READ; }
                    public File file() { return file; }
                    public String toString() {
                        return "redirect to read from file \"" + file + "\"";
                    }
                };
        }
        public static Redirect to(final File file) {
            if (file == null)
                throw new NullPointerException();
            return new Redirect() {
                    public Type type() { return Type.WRITE; }
                    public File file() { return file; }
                    public String toString() {
                        return "redirect to write to file \"" + file + "\"";
                    }
                    boolean append() { return false; }
                };
        }
        public static Redirect appendTo(final File file) {
            if (file == null)
                throw new NullPointerException();
            return new Redirect() {
                    public Type type() { return Type.APPEND; }
                    public File file() { return file; }
                    public String toString() {
                        return "redirect to append to file \"" + file + "\"";
                    }
                    boolean append() { return true; }
                };
        }
        public boolean equals(Object obj) {
            if (obj == this)
                return true;
            if (! (obj instanceof Redirect))
                return false;
            Redirect r = (Redirect) obj;
            if (r.type() != this.type())
                return false;
            assert this.file() != null;
            return this.file().equals(r.file());
        }
        public int hashCode() {
            File file = file();
            if (file == null)
                return super.hashCode();
            else
                return file.hashCode();
        }
        private Redirect() {}
    }
    static class RedirectPipeImpl extends Redirect {
        final FileDescriptor fd;
        RedirectPipeImpl() {
            this.fd = new FileDescriptor();
        }
        @Override
        public Type type() { return Type.PIPE; }
        @Override
        public String toString() { return type().toString();}
        FileDescriptor getFd() { return fd; }
    }
    private Redirect[] redirects() {
        if (redirects == null) {
            redirects = new Redirect[] {
                    Redirect.PIPE, Redirect.PIPE, Redirect.PIPE
            };
        }
        return redirects;
    }
    public ProcessBuilder redirectInput(Redirect source) {
        if (source.type() == Redirect.Type.WRITE ||
            source.type() == Redirect.Type.APPEND)
            throw new IllegalArgumentException(
                "Redirect invalid for reading: " + source);
        redirects()[0] = source;
        return this;
    }
    public ProcessBuilder redirectOutput(Redirect destination) {
        if (destination.type() == Redirect.Type.READ)
            throw new IllegalArgumentException(
                "Redirect invalid for writing: " + destination);
        redirects()[1] = destination;
        return this;
    }
    public ProcessBuilder redirectError(Redirect destination) {
        if (destination.type() == Redirect.Type.READ)
            throw new IllegalArgumentException(
                "Redirect invalid for writing: " + destination);
        redirects()[2] = destination;
        return this;
    }
    public ProcessBuilder redirectInput(File file) {
        return redirectInput(Redirect.from(file));
    }
    public ProcessBuilder redirectOutput(File file) {
        return redirectOutput(Redirect.to(file));
    }
    public ProcessBuilder redirectError(File file) {
        return redirectError(Redirect.to(file));
    }
    public Redirect redirectInput() {
        return (redirects == null) ? Redirect.PIPE : redirects[0];
    }
    public Redirect redirectOutput() {
        return (redirects == null) ? Redirect.PIPE : redirects[1];
    }
    public Redirect redirectError() {
        return (redirects == null) ? Redirect.PIPE : redirects[2];
    }
    public ProcessBuilder inheritIO() {
        Arrays.fill(redirects(), Redirect.INHERIT);
        return this;
    }
    public boolean redirectErrorStream() {
        return redirectErrorStream;
    }
    public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) {
        this.redirectErrorStream = redirectErrorStream;
        return this;
    }
    public Process start() throws IOException {
        return start(redirects);
    }
    private Process start(Redirect[] redirects) throws IOException {
        // Must convert to array first — a malicious user-supplied
        // list might try to circumvent the security check.
        String[] cmdarray = command.toArray(new String[command.size()]);
        cmdarray = cmdarray.clone();
        for (String arg : cmdarray)
            if (arg == null)
                throw new NullPointerException();
        // Throws IndexOutOfBoundsException if command is empty
        String prog = cmdarray[0];
        SecurityManager security = System.getSecurityManager();
        if (security != null)
            security.checkExec(prog);
        String dir = directory == null ? null : directory.toString();
        for (int i = 1; i < cmdarray.length; i++) {
            if (cmdarray[i].indexOf('\u0000') >= 0) {
                throw new IOException("invalid null character in command");
            }
        }
        try {
            return ProcessImpl.start(cmdarray,
                                     environment,
                                     dir,
                                     redirects,
                                     redirectErrorStream);
        } catch (IOException | IllegalArgumentException e) {
            String exceptionInfo = ": " + e.getMessage();
            Throwable cause = e;
            if ((e instanceof IOException) && security != null) {
                // Can not disclose the fail reason for read-protected files.
                try {
                    security.checkRead(prog);
                } catch (SecurityException se) {
                    exceptionInfo = "";
                    cause = se;
                }
            }
            // It's much easier for us to create a high-quality error
            // message than the low-level C code which found the problem.
            throw new IOException(
                "Cannot run program \"" + prog + "\""
                + (dir == null ? "" : " (in directory \"" + dir + "\")")
                + exceptionInfo,
                cause);
        }
    }
    public static List<Process> startPipeline(List<ProcessBuilder> builders) throws IOException {
        // Accumulate and check the builders
        final int numBuilders = builders.size();
        List<Process> processes = new ArrayList<>(numBuilders);
        try {
            Redirect prevOutput = null;
            for (int index = 0; index < builders.size(); index++) {
                ProcessBuilder builder = builders.get(index);
                Redirect[] redirects = builder.redirects();
                if (index > 0) {
                    // check the current Builder to see if it can take input from the previous
                    if (builder.redirectInput() != Redirect.PIPE) {
                        throw new IllegalArgumentException("builder redirectInput()" +
                                " must be PIPE except for the first builder: "
                                + builder.redirectInput());
                    }
                    redirects[0] = prevOutput;
                }
                if (index < numBuilders – 1) {
                    // check all but the last stage has output = PIPE
                    if (builder.redirectOutput() != Redirect.PIPE) {
                        throw new IllegalArgumentException("builder redirectOutput()" +
                                " must be PIPE except for the last builder: "
                                + builder.redirectOutput());
                    }
                    redirects[1] = new RedirectPipeImpl();  // placeholder for new output
                }
                processes.add(builder.start(redirects));
                prevOutput = redirects[1];
            }
        } catch (Exception ex) {
            // Cleanup processes already started
            processes.forEach(Process::destroyForcibly);
            processes.forEach(p -> {
                try {
                    p.waitFor();        // Wait for it to exit
                } catch (InterruptedException ie) {
                    // If interrupted; continue with next Process
                    Thread.currentThread().interrupt();
                }
            });
            throw ex;
        }
        return processes;
    }
}
JDK

java.lang.Processクラスのソースコード

Javaから外部プログラムを実行する際にプロセスを管理するjava.lang.Processクラスのソースコードを見てみよう。標準入出力とエラー出力へのStreamや,終了コードを返すexitValue()メソッド,プロセスを終了させるdestroy()メソッドは抽象メソッドとなっている。

/*
 * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;
import java.io.*;
import java.lang.ProcessBuilder.Redirect;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
public abstract class Process {
    public Process() {}
    public abstract OutputStream getOutputStream();
    public abstract InputStream getInputStream();
    public abstract InputStream getErrorStream();
    public abstract int waitFor() throws InterruptedException;
    public boolean waitFor(long timeout, TimeUnit unit)
        throws InterruptedException
    {
        long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions
        if (hasExited())
            return true;
        if (timeout <= 0)
            return false;
        long deadline = System.nanoTime() + remainingNanos;
        do {
            Thread.sleep(Math.min(TimeUnit.NANOSECONDS.toMillis(remainingNanos) + 1, 100));
            if (hasExited())
                return true;
            remainingNanos = deadline – System.nanoTime();
        } while (remainingNanos > 0);
        return false;
    }
    public abstract int exitValue();
    public abstract void destroy();
    public Process destroyForcibly() {
        destroy();
        return this;
    }
    public boolean supportsNormalTermination() {
        throw new UnsupportedOperationException(this.getClass()
                + ".supportsNormalTermination() not supported" );
    }
    public boolean isAlive() {
        return !hasExited();
    }
    private boolean hasExited() {
        try {
            exitValue();
            return true;
        } catch (IllegalThreadStateException e) {
            return false;
        }
    }
    public long pid() {
        return toHandle().pid();
    }
    public CompletableFuture<Process> onExit() {
        return CompletableFuture.supplyAsync(this::waitForInternal);
    }
    private Process waitForInternal() {
        boolean interrupted = false;
        while (true) {
            try {
                ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker() {
                    @Override
                    public boolean block() throws InterruptedException {
                        waitFor();
                        return true;
                    }
                    @Override
                    public boolean isReleasable() {
                        return !isAlive();
                    }
                });
                break;
            } catch (InterruptedException x) {
                interrupted = true;
            }
        }
        if (interrupted) {
            Thread.currentThread().interrupt();
        }
        return this;
    }
    public ProcessHandle toHandle() {
        throw new UnsupportedOperationException(this.getClass()
                + ".toHandle() not supported");
    }
    public ProcessHandle.Info info() {
        return toHandle().info();
    }
    public Stream<ProcessHandle> children() {
        return toHandle().children();
    }
    public Stream<ProcessHandle> descendants() {
        return toHandle().descendants();
    }
    static class PipeInputStream extends FileInputStream {
        PipeInputStream(FileDescriptor fd) {
            super(fd);
        }
        @Override
        public long skip(long n) throws IOException {
            long remaining = n;
            int nr;
            if (n <= 0) {
                return 0;
            }
            int size = (int)Math.min(2048, remaining);
            byte[] skipBuffer = new byte[size];
            while (remaining > 0) {
                nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
                if (nr < 0) {
                    break;
                }
                remaining -= nr;
            }
            return n – remaining;
        }
    }
}
JDK

java.lang.StringBufferクラスのソースコード

StringBuilderと同様に文字列を操作するためのクラスStringBufferクラスのソースコードを紹介する。機能はStringBuilderと同じだが,StringBufferはスレッドセーフな設計になっている。多くのメソッドにsynchronizedが付されている。それ以外は,StringBuilderの実装と同様に,スーパークラスであるAbstractStringBuilderクラスのメソッドを呼び出しているものが多い。

/*
 * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;
import java.util.Arrays;
import jdk.internal.HotSpotIntrinsicCandidate;
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
{
    private transient String toStringCache;
    static final long serialVersionUID = 3388685877147921107L;
    @HotSpotIntrinsicCandidate
    public StringBuffer() {
        super(16);
    }
    @HotSpotIntrinsicCandidate
    public StringBuffer(int capacity) {
        super(capacity);
    }
    @HotSpotIntrinsicCandidate
    public StringBuffer(String str) {
        super(str);
    }
    public StringBuffer(CharSequence seq) {
        super(seq);
    }
    @Override
    public synchronized int compareTo(StringBuffer another) {
        return super.compareTo(another);
    }
    @Override
    public synchronized int length() {
        return count;
    }
    @Override
    public synchronized int capacity() {
        return super.capacity();
    }
    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }
    @Override
    public synchronized void trimToSize() {
        super.trimToSize();
    }
    @Override
    public synchronized void setLength(int newLength) {
        toStringCache = null;
        super.setLength(newLength);
    }
    @Override
    public synchronized char charAt(int index) {
        return super.charAt(index);
    }
    @Override
    public synchronized int codePointAt(int index) {
        return super.codePointAt(index);
    }
    @Override
    public synchronized int codePointBefore(int index) {
        return super.codePointBefore(index);
    }
    @Override
    public synchronized int codePointCount(int beginIndex, int endIndex) {
        return super.codePointCount(beginIndex, endIndex);
    }
    @Override
    public synchronized int offsetByCodePoints(int index, int codePointOffset) {
        return super.offsetByCodePoints(index, codePointOffset);
    }
    @Override
    public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                      int dstBegin)
    {
        super.getChars(srcBegin, srcEnd, dst, dstBegin);
    }
    @Override
    public synchronized void setCharAt(int index, char ch) {
        toStringCache = null;
        super.setCharAt(index, ch);
    }
    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }
    @Override
    @HotSpotIntrinsicCandidate
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    public synchronized StringBuffer append(StringBuffer sb) {
        toStringCache = null;
        super.append(sb);
        return this;
    }
    @Override
    synchronized StringBuffer append(AbstractStringBuilder asb) {
        toStringCache = null;
        super.append(asb);
        return this;
    }
    @Override
    public synchronized StringBuffer append(CharSequence s) {
        toStringCache = null;
        super.append(s);
        return this;
    }
    @Override
    public synchronized StringBuffer append(CharSequence s, int start, int end)
    {
        toStringCache = null;
        super.append(s, start, end);
        return this;
    }
    @Override
    public synchronized StringBuffer append(char[] str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    @Override
    public synchronized StringBuffer append(char[] str, int offset, int len) {
        toStringCache = null;
        super.append(str, offset, len);
        return this;
    }
    @Override
    public synchronized StringBuffer append(boolean b) {
        toStringCache = null;
        super.append(b);
        return this;
    }
    @Override
    @HotSpotIntrinsicCandidate
    public synchronized StringBuffer append(char c) {
        toStringCache = null;
        super.append(c);
        return this;
    }
    @Override
    @HotSpotIntrinsicCandidate
    public synchronized StringBuffer append(int i) {
        toStringCache = null;
        super.append(i);
        return this;
    }
    @Override
    public synchronized StringBuffer appendCodePoint(int codePoint) {
        toStringCache = null;
        super.appendCodePoint(codePoint);
        return this;
    }
    @Override
    public synchronized StringBuffer append(long lng) {
        toStringCache = null;
        super.append(lng);
        return this;
    }
    @Override
    public synchronized StringBuffer append(float f) {
        toStringCache = null;
        super.append(f);
        return this;
    }
    @Override
    public synchronized StringBuffer append(double d) {
        toStringCache = null;
        super.append(d);
        return this;
    }
    @Override
    public synchronized StringBuffer delete(int start, int end) {
        toStringCache = null;
        super.delete(start, end);
        return this;
    }
    @Override
    public synchronized StringBuffer deleteCharAt(int index) {
        toStringCache = null;
        super.deleteCharAt(index);
        return this;
    }
    @Override
    public synchronized StringBuffer replace(int start, int end, String str) {
        toStringCache = null;
        super.replace(start, end, str);
        return this;
    }
    @Override
    public synchronized String substring(int start) {
        return substring(start, count);
    }
    @Override
    public synchronized CharSequence subSequence(int start, int end) {
        return super.substring(start, end);
    }
    @Override
    public synchronized String substring(int start, int end) {
        return super.substring(start, end);
    }
    @Override
    public synchronized StringBuffer insert(int index, char[] str, int offset,
                                            int len)
    {
        toStringCache = null;
        super.insert(index, str, offset, len);
        return this;
    }
    @Override
    public synchronized StringBuffer insert(int offset, Object obj) {
        toStringCache = null;
        super.insert(offset, String.valueOf(obj));
        return this;
    }
    @Override
    public synchronized StringBuffer insert(int offset, String str) {
        toStringCache = null;
        super.insert(offset, str);
        return this;
    }
    @Override
    public synchronized StringBuffer insert(int offset, char[] str) {
        toStringCache = null;
        super.insert(offset, str);
        return this;
    }
    @Override
    public StringBuffer insert(int dstOffset, CharSequence s) {
        // Note, synchronization achieved via invocations of other StringBuffer methods
        // after narrowing of s to specific type
        // Ditto for toStringCache clearing
        super.insert(dstOffset, s);
        return this;
    }
    @Override
    public synchronized StringBuffer insert(int dstOffset, CharSequence s,
            int start, int end)
    {
        toStringCache = null;
        super.insert(dstOffset, s, start, end);
        return this;
    }
    @Override
    public  StringBuffer insert(int offset, boolean b) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of b to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, b);
        return this;
    }
    @Override
    public synchronized StringBuffer insert(int offset, char c) {
        toStringCache = null;
        super.insert(offset, c);
        return this;
    }
    @Override
    public StringBuffer insert(int offset, int i) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of i to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, i);
        return this;
    }
    @Override
    public StringBuffer insert(int offset, long l) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of l to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, l);
        return this;
    }
    @Override
    public StringBuffer insert(int offset, float f) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of f to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, f);
        return this;
    }
    @Override
    public StringBuffer insert(int offset, double d) {
        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
        // after conversion of d to String by super class method
        // Ditto for toStringCache clearing
        super.insert(offset, d);
        return this;
    }
    @Override
    public int indexOf(String str) {
        // Note, synchronization achieved via invocations of other StringBuffer methods
        return super.indexOf(str);
    }
    @Override
    public synchronized int indexOf(String str, int fromIndex) {
        return super.indexOf(str, fromIndex);
    }
    @Override
    public int lastIndexOf(String str) {
        // Note, synchronization achieved via invocations of other StringBuffer methods
        return lastIndexOf(str, count);
    }
    @Override
    public synchronized int lastIndexOf(String str, int fromIndex) {
        return super.lastIndexOf(str, fromIndex);
    }
    @Override
    public synchronized StringBuffer reverse() {
        toStringCache = null;
        super.reverse();
        return this;
    }
    @Override
    @HotSpotIntrinsicCandidate
    public synchronized String toString() {
        if (toStringCache == null) {
            return toStringCache =
                    isLatin1() ? StringLatin1.newString(value, 0, count)
                               : StringUTF16.newString(value, 0, count);
        }
        return new String(toStringCache);
    }
    private static final java.io.ObjectStreamField[] serialPersistentFields =
    {
        new java.io.ObjectStreamField("value", char[].class),
        new java.io.ObjectStreamField("count", Integer.TYPE),
        new java.io.ObjectStreamField("shared", Boolean.TYPE),
    };
    private synchronized void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        java.io.ObjectOutputStream.PutField fields = s.putFields();
        char[] val = new char[capacity()];
        if (isLatin1()) {
            StringLatin1.getChars(value, 0, count, val, 0);
        } else {
            StringUTF16.getChars(value, 0, count, val, 0);
        }
        fields.put("value", val);
        fields.put("count", count);
        fields.put("shared", false);
        s.writeFields();
    }
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        java.io.ObjectInputStream.GetField fields = s.readFields();
        char[] val = (char[])fields.get("value", null);
        initBytes(val, 0, val.length);
        count = fields.get("count", 0);
    }
    synchronized void getBytes(byte dst[], int dstBegin, byte coder) {
        super.getBytes(dst, dstBegin, coder);
    }
}
JDK

java.lang.StringBuilderクラスのソースコード

java.lang.StringBuilderクラスのソースコードを紹介する。文字列操作には欠かせないクラスである。初期のサイズは16文字であり,意外に小さい。

 ほとんどのメソッドはスーパークラスのメソッドを呼び出すようになっている。独自に実装されているのは,末尾にあるreadObjectg()メソッドとwriteObject()メソッドくらいだ。

/*
 * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the “Classpath” exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{
    static final long serialVersionUID = 4383685877147921099L;
    @HotSpotIntrinsicCandidate
    public StringBuilder() {
        super(16);
    }
    @HotSpotIntrinsicCandidate
    public StringBuilder(int capacity) {
        super(capacity);
    }
    @HotSpotIntrinsicCandidate
    public StringBuilder(String str) {
        super(str);
    }
    public StringBuilder(CharSequence seq) {
        super(seq);
    }
    @Override
    public int compareTo(StringBuilder another) {
        return super.compareTo(another);
    }
    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }
    @Override
    @HotSpotIntrinsicCandidate
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    public StringBuilder append(StringBuffer sb) {
        super.append(sb);
        return this;
    }
    @Override
    public StringBuilder append(CharSequence s) {
        super.append(s);
        return this;
    }
    @Override
    public StringBuilder append(CharSequence s, int start, int end) {
        super.append(s, start, end);
        return this;
    }
    @Override
    public StringBuilder append(char[] str) {
        super.append(str);
        return this;
    }
    @Override
    public StringBuilder append(char[] str, int offset, int len) {
        super.append(str, offset, len);
        return this;
    }
    @Override
    public StringBuilder append(boolean b) {
        super.append(b);
        return this;
    }
    @Override
    @HotSpotIntrinsicCandidate
    public StringBuilder append(char c) {
        super.append(c);
        return this;
    }
    @Override
    @HotSpotIntrinsicCandidate
    public StringBuilder append(int i) {
        super.append(i);
        return this;
    }
    @Override
    public StringBuilder append(long lng) {
        super.append(lng);
        return this;
    }
    @Override
    public StringBuilder append(float f) {
        super.append(f);
        return this;
    }
    @Override
    public StringBuilder append(double d) {
        super.append(d);
        return this;
    }
    @Override
    public StringBuilder appendCodePoint(int codePoint) {
        super.appendCodePoint(codePoint);
        return this;
    }
    @Override
    public StringBuilder delete(int start, int end) {
        super.delete(start, end);
        return this;
    }
    @Override
    public StringBuilder deleteCharAt(int index) {
        super.deleteCharAt(index);
        return this;
    }
    @Override
    public StringBuilder replace(int start, int end, String str) {
        super.replace(start, end, str);
        return this;
    }
    @Override
    public StringBuilder insert(int index, char[] str, int offset,
                                int len)
    {
        super.insert(index, str, offset, len);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, Object obj) {
            super.insert(offset, obj);
            return this;
    }
    @Override
    public StringBuilder insert(int offset, String str) {
        super.insert(offset, str);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, char[] str) {
        super.insert(offset, str);
        return this;
    }
    @Override
    public StringBuilder insert(int dstOffset, CharSequence s) {
            super.insert(dstOffset, s);
            return this;
    }
    @Override
    public StringBuilder insert(int dstOffset, CharSequence s,
                                int start, int end)
    {
        super.insert(dstOffset, s, start, end);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, boolean b) {
        super.insert(offset, b);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, char c) {
        super.insert(offset, c);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, int i) {
        super.insert(offset, i);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, long l) {
        super.insert(offset, l);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, float f) {
        super.insert(offset, f);
        return this;
    }
    @Override
    public StringBuilder insert(int offset, double d) {
        super.insert(offset, d);
        return this;
    }
    @Override
    public int indexOf(String str) {
        return super.indexOf(str);
    }
    @Override
    public int indexOf(String str, int fromIndex) {
        return super.indexOf(str, fromIndex);
    }
    @Override
    public int lastIndexOf(String str) {
        return super.lastIndexOf(str);
    }
    @Override
    public int lastIndexOf(String str, int fromIndex) {
        return super.lastIndexOf(str, fromIndex);
    }
    @Override
    public StringBuilder reverse() {
        super.reverse();
        return this;
    }
    @Override
    @HotSpotIntrinsicCandidate
    public String toString() {
        // Create a copy, don’t share the array
        return isLatin1() ? StringLatin1.newString(value, 0, count)
                          : StringUTF16.newString(value, 0, count);
    }
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        s.defaultWriteObject();
        s.writeInt(count);
        char[] val = new char[capacity()];
        if (isLatin1()) {
            StringLatin1.getChars(value, 0, count, val, 0);
        } else {
            StringUTF16.getChars(value, 0, count, val, 0);
        }
        s.writeObject(val);
    }
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        count = s.readInt();
        char[] val = (char[]) s.readObject();
        initBytes(val, 0, val.length);
    }
}
JDK

java.lang.AbstractStringBuilderクラスのコード

今回は,StringBuilderおよびStringBufferの共通のスーパークラスであるAbstractStringBuilderのコードを読んでみよう。StringBuilderとStringBufferの主要なメソッドはほぼ網羅されている。これらのクラスの違いはスレッドセーフか否かの違いでしかないため,共通する多くの実装コードはこのスーパークラスの書かれている。このクラスはpackage private(ディフォルト)なクラスであるため,パッケージ外からはアクセスできない。

フィールド定義を見ると,文字列がbyte[]配列で表現されていることがわかる。そのため,配列サイズの限界(Integer.MAX_VALUE)より長い文字列は扱えない。長さはcountというフィールドで保持している。C言語のように終端文字で判定しているわけではない。

コンストラクタとappend()メソッドとinsert()メソッドは,引数の違いにより多くの種類がオーバーロードされていることがわかる。

/*
 * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the “Classpath” exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.lang;

import jdk.internal.math.FloatingDecimal;
import java.util.Arrays;
import java.util.Spliterator;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;

import static java.lang.String.COMPACT_STRINGS;
import static java.lang.String.UTF16;
import static java.lang.String.LATIN1;
import static java.lang.String.checkIndex;
import static java.lang.String.checkOffset;

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    byte[] value;
    byte coder;
    int count;
    private static final byte[] EMPTYVALUE = new byte[0];
    AbstractStringBuilder() {
        value = EMPTYVALUE;
    }
    AbstractStringBuilder(int capacity) {
        if (COMPACT_STRINGS) {
            value = new byte[capacity];
            coder = LATIN1;
        } else {
            value = StringUTF16.newBytesFor(capacity);
            coder = UTF16;
        }
    }
    AbstractStringBuilder(String str) {
        int length = str.length();
        int capacity = (length < Integer.MAX_VALUE – 16)
                ? length + 16 : Integer.MAX_VALUE;
        final byte initCoder = str.coder();
        coder = initCoder;
        value = (initCoder == LATIN1)
                ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
        append(str);
    }
    AbstractStringBuilder(CharSequence seq) {
        int length = seq.length();
        if (length < 0) {
            throw new NegativeArraySizeException(“Negative length: ” + length);
        }
        int capacity = (length < Integer.MAX_VALUE – 16)
                ? length + 16 : Integer.MAX_VALUE;
        final byte initCoder;
        if (COMPACT_STRINGS) {
            if (seq instanceof AbstractStringBuilder) {
                initCoder = ((AbstractStringBuilder)seq).getCoder();
            } else if (seq instanceof String) {
                initCoder = ((String)seq).coder();
            } else {
                initCoder = LATIN1;
            }
        } else {
            initCoder = UTF16;
        }
        coder = initCoder;
        value = (initCoder == LATIN1)
                ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
        append(seq);
    }
    int compareTo(AbstractStringBuilder another) {
        if (this == another) {
            return 0;
        }
        byte val1[] = value;
        byte val2[] = another.value;
        int count1 = this.count;
        int count2 = another.count;
        if (coder == another.coder) {
            return isLatin1() ? StringLatin1.compareTo(val1, val2, count1, count2)
                              : StringUTF16.compareTo(val1, val2, count1, count2);
        }
        return isLatin1() ? StringLatin1.compareToUTF16(val1, val2, count1, count2)
                          : StringUTF16.compareToLatin1(val1, val2, count1, count2);
    }
    @Override
    public int length() {
        return count;
    }
    public int capacity() {
        return value.length >> coder;
    }
    public void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity > 0) {
            ensureCapacityInternal(minimumCapacity);
        }
    }
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        int oldCapacity = value.length >> coder;
        if (minimumCapacity – oldCapacity > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity) << coder);
        }
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE – 8;
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = value.length >> coder;
        int newCapacity = (oldCapacity << 1) + 2;
        if (newCapacity – minCapacity < 0) {
            newCapacity = minCapacity;
        }
        int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
        return (newCapacity <= 0 || SAFE_BOUND – newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
    private int hugeCapacity(int minCapacity) {
        int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
        int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
        if (UNSAFE_BOUND – minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > SAFE_BOUND)
            ? minCapacity : SAFE_BOUND;
    }
    private void inflate() {
        if (!isLatin1()) {
            return;
        }
        byte[] buf = StringUTF16.newBytesFor(value.length);
        StringLatin1.inflate(value, 0, buf, 0, count);
        this.value = buf;
        this.coder = UTF16;
    }
    public void trimToSize() {
        int length = count << coder;
        if (length < value.length) {
            value = Arrays.copyOf(value, length);
        }
    }
    public void setLength(int newLength) {
        if (newLength < 0) {
            throw new StringIndexOutOfBoundsException(newLength);
        }
        ensureCapacityInternal(newLength);
        if (count < newLength) {
            if (isLatin1()) {
                StringLatin1.fillNull(value, count, newLength);
            } else {
                StringUTF16.fillNull(value, count, newLength);
            }
        }
        count = newLength;
    }
    @Override
    public char charAt(int index) {
        checkIndex(index, count);
        if (isLatin1()) {
            return (char)(value[index] & 0xff);
        }
        return StringUTF16.charAt(value, index);
    }
    public int codePointAt(int index) {
        int count = this.count;
        byte[] value = this.value;
        checkIndex(index, count);
        if (isLatin1()) {
            return value[index] & 0xff;
        }
        return StringUTF16.codePointAtSB(value, index, count);
    }
    public int codePointBefore(int index) {
        int i = index – 1;
        if (i < 0 || i >= count) {
            throw new StringIndexOutOfBoundsException(index);
        }
        if (isLatin1()) {
            return value[i] & 0xff;
        }
        return StringUTF16.codePointBeforeSB(value, index);
    }
    public int codePointCount(int beginIndex, int endIndex) {
        if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
            throw new IndexOutOfBoundsException();
        }
        if (isLatin1()) {
            return endIndex – beginIndex;
        }
        return StringUTF16.codePointCountSB(value, beginIndex, endIndex);
    }
    public int offsetByCodePoints(int index, int codePointOffset) {
        if (index < 0 || index > count) {
            throw new IndexOutOfBoundsException();
        }
        return Character.offsetByCodePoints(this,
                                            index, codePointOffset);
    }
    public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
    {
        checkRangeSIOOBE(srcBegin, srcEnd, count);  // compatible to old version
        int n = srcEnd – srcBegin;
        checkRange(dstBegin, dstBegin + n, dst.length);
        if (isLatin1()) {
            StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);
        } else {
            StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);
        }
    }
    public void setCharAt(int index, char ch) {
        checkIndex(index, count);
        if (isLatin1() && StringLatin1.canEncode(ch)) {
            value[index] = (byte)ch;
        } else {
            if (isLatin1()) {
                inflate();
            }
            StringUTF16.putCharSB(value, index, ch);
        }
    }
    //——— append()メソッドの実装 ———————
    public AbstractStringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }
    public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        putStringAt(count, str);
        count += len;
        return this;
    }
    public AbstractStringBuilder append(StringBuffer sb) {
        return this.append((AbstractStringBuilder)sb);
    }
    AbstractStringBuilder append(AbstractStringBuilder asb) {
        if (asb == null) {
            return appendNull();
        }
        int len = asb.length();
        ensureCapacityInternal(count + len);
        if (getCoder() != asb.getCoder()) {
            inflate();
        }
        asb.getBytes(value, count, coder);
        count += len;
        return this;
    }
    @Override
    public AbstractStringBuilder append(CharSequence s) {
        if (s == null) {
            return appendNull();
        }
        if (s instanceof String) {
            return this.append((String)s);
        }
        if (s instanceof AbstractStringBuilder) {
            return this.append((AbstractStringBuilder)s);
        }
        return this.append(s, 0, s.length());
    }
    private AbstractStringBuilder appendNull() {
        ensureCapacityInternal(count + 4);
        int count = this.count;
        byte[] val = this.value;
        if (isLatin1()) {
            val[count++] = ‘n’;
            val[count++] = ‘u’;
            val[count++] = ‘l’;
            val[count++] = ‘l’;
        } else {
            count = StringUTF16.putCharsAt(val, count, ‘n’, ‘u’, ‘l’, ‘l’);
        }
        this.count = count;
        return this;
    }
    @Override
    public AbstractStringBuilder append(CharSequence s, int start, int end) {
        if (s == null) {
            s = “null”;
        }
        checkRange(start, end, s.length());
        int len = end – start;
        ensureCapacityInternal(count + len);
        appendChars(s, start, end);
        return this;
    }
    public AbstractStringBuilder append(char[] str) {
        int len = str.length;
        ensureCapacityInternal(count + len);
        appendChars(str, 0, len);
        return this;
    }
    public AbstractStringBuilder append(char str[], int offset, int len) {
        int end = offset + len;
        checkRange(offset, end, str.length);
        ensureCapacityInternal(count + len);
        appendChars(str, offset, end);
        return this;
    }
    public AbstractStringBuilder append(boolean b) {
        ensureCapacityInternal(count + (b ? 4 : 5));
        int count = this.count;
        byte[] val = this.value;
        if (isLatin1()) {
            if (b) {
                val[count++] = ‘t’;
                val[count++] = ‘r’;
                val[count++] = ‘u’;
                val[count++] = ‘e’;
            } else {
                val[count++] = ‘f’;
                val[count++] = ‘a’;
                val[count++] = ‘l’;
                val[count++] = ‘s’;
                val[count++] = ‘e’;
            }
        } else {
            if (b) {
                count = StringUTF16.putCharsAt(val, count, ‘t’, ‘r’, ‘u’, ‘e’);
            } else {
                count = StringUTF16.putCharsAt(val, count, ‘f’, ‘a’, ‘l’, ‘s’, ‘e’);
            }
        }
        this.count = count;
        return this;
    }
    @Override
    public AbstractStringBuilder append(char c) {
        ensureCapacityInternal(count + 1);
        if (isLatin1() && StringLatin1.canEncode(c)) {
            value[count++] = (byte)c;
        } else {
            if (isLatin1()) {
                inflate();
            }
            StringUTF16.putCharSB(value, count++, c);
        }
        return this;
    }
    public AbstractStringBuilder append(int i) {
        int count = this.count;
        int spaceNeeded = count + Integer.stringSize(i);
        ensureCapacityInternal(spaceNeeded);
        if (isLatin1()) {
            Integer.getChars(i, spaceNeeded, value);
        } else {
            StringUTF16.getChars(i, count, spaceNeeded, value);
        }
        this.count = spaceNeeded;
        return this;
    }
    public AbstractStringBuilder append(long l) {
        int count = this.count;
        int spaceNeeded = count + Long.stringSize(l);
        ensureCapacityInternal(spaceNeeded);
        if (isLatin1()) {
            Long.getChars(l, spaceNeeded, value);
        } else {
            StringUTF16.getChars(l, count, spaceNeeded, value);
        }
        this.count = spaceNeeded;
        return this;
    }
    public AbstractStringBuilder append(float f) {
        FloatingDecimal.appendTo(f,this);
        return this;
    }
    public AbstractStringBuilder append(double d) {
        FloatingDecimal.appendTo(d,this);
        return this;
    }
    // —————————————————–
    public AbstractStringBuilder delete(int start, int end) {
        int count = this.count;
        if (end > count) {
            end = count;
        }
        checkRangeSIOOBE(start, end, count);
        int len = end – start;
        if (len > 0) {
            shift(end, -len);
            this.count = count – len;
        }
        return this;
    }
    public AbstractStringBuilder appendCodePoint(int codePoint) {
        if (Character.isBmpCodePoint(codePoint)) {
            return append((char)codePoint);
        }
        return append(Character.toChars(codePoint));
    }
    public AbstractStringBuilder deleteCharAt(int index) {
        checkIndex(index, count);
        shift(index + 1, -1);
        count–;
        return this;
    }
    public AbstractStringBuilder replace(int start, int end, String str) {
        int count = this.count;
        if (end > count) {
            end = count;
        }
        checkRangeSIOOBE(start, end, count);
        int len = str.length();
        int newCount = count + len – (end – start);
        ensureCapacityInternal(newCount);
        shift(end, newCount – count);
        this.count = newCount;
        putStringAt(start, str);
        return this;
    }
    public String substring(int start) {
        return substring(start, count);
    }
    @Override
    public CharSequence subSequence(int start, int end) {
        return substring(start, end);
    }
    public String substring(int start, int end) {
        checkRangeSIOOBE(start, end, count);
        if (isLatin1()) {
            return StringLatin1.newString(value, start, end – start);
        }
        return StringUTF16.newString(value, start, end – start);
    }
    // —————- insert()メソッド ——————
    public AbstractStringBuilder insert(int index, char[] str, int offset,
                                        int len)
    {
        checkOffset(index, count);
        checkRangeSIOOBE(offset, offset + len, str.length);
        ensureCapacityInternal(count + len);
        shift(index, len);
        count += len;
        putCharsAt(index, str, offset, offset + len);
        return this;
    }
    public AbstractStringBuilder insert(int offset, Object obj) {
        return insert(offset, String.valueOf(obj));
    }
    public AbstractStringBuilder insert(int offset, String str) {
        checkOffset(offset, count);
        if (str == null) {
            str = “null”;
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        shift(offset, len);
        count += len;
        putStringAt(offset, str);
        return this;
    }
    public AbstractStringBuilder insert(int offset, char[] str) {
        checkOffset(offset, count);
        int len = str.length;
        ensureCapacityInternal(count + len);
        shift(offset, len);
        count += len;
        putCharsAt(offset, str, 0, len);
        return this;
    }
    public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
        if (s == null) {
            s = “null”;
        }
        if (s instanceof String) {
            return this.insert(dstOffset, (String)s);
        }
        return this.insert(dstOffset, s, 0, s.length());
    }
    public AbstractStringBuilder insert(int dstOffset, CharSequence s,
                                        int start, int end)
    {
        if (s == null) {
            s = “null”;
        }
        checkOffset(dstOffset, count);
        checkRange(start, end, s.length());
        int len = end – start;
        ensureCapacityInternal(count + len);
        shift(dstOffset, len);
        count += len;
        putCharsAt(dstOffset, s, start, end);
        return this;
    }
    public AbstractStringBuilder insert(int offset, boolean b) {
        return insert(offset, String.valueOf(b));
    }
    public AbstractStringBuilder insert(int offset, char c) {
        checkOffset(offset, count);
        ensureCapacityInternal(count + 1);
        shift(offset, 1);
        count += 1;
        if (isLatin1() && StringLatin1.canEncode(c)) {
            value[offset] = (byte)c;
        } else {
            if (isLatin1()) {
                inflate();
            }
            StringUTF16.putCharSB(value, offset, c);
        }
        return this;
    }
    public AbstractStringBuilder insert(int offset, int i) {
        return insert(offset, String.valueOf(i));
    }
    public AbstractStringBuilder insert(int offset, long l) {
        return insert(offset, String.valueOf(l));
    }
    public AbstractStringBuilder insert(int offset, float f) {
        return insert(offset, String.valueOf(f));
    }
    public AbstractStringBuilder insert(int offset, double d) {
        return insert(offset, String.valueOf(d));
    }
    //——————————————————
    public int indexOf(String str) {
        return indexOf(str, 0);
    }
    public int indexOf(String str, int fromIndex) {
        return String.indexOf(value, coder, count, str, fromIndex);
    }
    public int lastIndexOf(String str) {
        return lastIndexOf(str, count);
    }
    public int lastIndexOf(String str, int fromIndex) {
        return String.lastIndexOf(value, coder, count, str, fromIndex);
    }
    public AbstractStringBuilder reverse() {
        byte[] val = this.value;
        int count = this.count;
        int coder = this.coder;
        int n = count – 1;
        if (COMPACT_STRINGS && coder == LATIN1) {
            for (int j = (n-1) >> 1; j >= 0; j–) {
                int k = n – j;
                byte cj = val[j];
                val[j] = val[k];
                val[k] = cj;
            }
        } else {
            StringUTF16.reverse(val, count);
        }
        return this;
    }
    @Override
    public abstract String toString();
    @Override
    public IntStream chars() {
        // Reuse String-based spliterator. This requires a supplier to
        // capture the value and count when the terminal operation is executed
        return StreamSupport.intStream(
                () -> {
                    // The combined set of field reads are not atomic and thread
                    // safe but bounds checks will ensure no unsafe reads from
                    // the byte array
                    byte[] val = this.value;
                    int count = this.count;
                    byte coder = this.coder;
                    return coder == LATIN1
                           ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
                           : new StringUTF16.CharsSpliterator(val, 0, count, 0);
                },
                Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
                false);
    }
    @Override
    public IntStream codePoints() {
        return StreamSupport.intStream(
                () -> {
                    byte[] val = this.value;
                    int count = this.count;
                    byte coder = this.coder;
                    return coder == LATIN1
                           ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
                           : new StringUTF16.CodePointsSpliterator(val, 0, count, 0);
                },
                Spliterator.ORDERED,
                false);
    }
    final byte[] getValue() {
        return value;
    }
    void getBytes(byte dst[], int dstBegin, byte coder) {
        if (this.coder == coder) {
            System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
        } else {        // this.coder == LATIN && coder == UTF16
            StringLatin1.inflate(value, 0, dst, dstBegin, count);
        }
    }
    void initBytes(char[] value, int off, int len) {
        if (String.COMPACT_STRINGS) {
            this.value = StringUTF16.compress(value, off, len);
            if (this.value != null) {
                this.coder = LATIN1;
                return;
            }
        }
        this.coder = UTF16;
        this.value = StringUTF16.toBytes(value, off, len);
    }
    private final void appendChars(char[] s, int off, int end) {
        int count = this.count;
        if (isLatin1()) {
            byte[] val = this.value;
            for (int i = off, j = count; i < end; i++) {
                char c = s[i];
                if (StringLatin1.canEncode(c)) {
                    val[j++] = (byte)c;
                } else {
                    this.count = count = j;
                    inflate();
                    StringUTF16.putCharsSB(this.value, j, s, i, end);
                    this.count = count + end – i;
                    return;
                }
            }
        } else {
            StringUTF16.putCharsSB(this.value, count, s, off, end);
        }
        this.count = count + end – off;
    }

    private final void appendChars(CharSequence s, int off, int end) {
        if (isLatin1()) {
            byte[] val = this.value;
            for (int i = off, j = count; i < end; i++) {
                char c = s.charAt(i);
                if (StringLatin1.canEncode(c)) {
                    val[j++] = (byte)c;
                } else {
                    count = j;
                    inflate();
                    StringUTF16.putCharsSB(this.value, j, s, i, end);
                    count += end – i;
                    return;
                }
            }
        } else {
            StringUTF16.putCharsSB(this.value, count, s, off, end);
        }
        count += end – off;
    }
}

JDK

java.lang.Comparableインタフェースのソース

 java.lang.Comparable<T>インタフェースは,オブジェクト同士の大小は決定するメソッドcompareTo(T o)のみを宣言したものである。自身が比較対象オブジェクトより大きい場合は正,同じ場合はゼロ,小さい場合は負の整数を返すよう実装する。

/*
 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the “Classpath” exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.lang;
import java.util.*;

/*
 *
 * @author  Josh Bloch
 * @see java.util.Comparator
 * @since 1.2
 */
public interface Comparable<T> {
    /**
     * Compares this object with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     * @param   o the object to be compared.
     * @return  a negative integer, zero, or a positive integer as this object
     *          is less than, equal to, or greater than the specified object.
     *
     * @throws NullPointerException if the specified object is null
     * @throws ClassCastException if the specified object’s type prevents it
     *         from being compared to this object.
     */
    public int compareTo(T o);
}
JDK

java.lang.Throwableクラスのソースコード

今回はjava.lang.Throwableクラスのソースコードを読んでみる。これはエラーでスローされる例外の最上位のクラスである。try-carhでThrowableをキャッチすれば,すべてのエラーをキャッチできる(JVMのエラーまでキャッチしてしまうため,適切ではない)。

 publicなコンストラクタが4種類定義されているので,インスタンスを作成することは可能であるが,やはりするべきではない書き方と言えよう。ユーザ例外を定義する場合は,java.lang.Exception,あるいは,java.lang.RuntimeExceptionを継承して作成する。

 定義されているメソッドは,エラーメッセージを管理するためのメソッドと,スタックトレースを管理するためのメソッドである。例外クラスの実質的な機能は,ほぼjava.lang.Throwableクラスで実装されていると言える。

/*
 * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the “Classpath” exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.lang;

import  java.io.*;
import  java.util.*;

public class Throwable implements Serializable {
    private transient Object backtrace;
    private String detailMessage;
    private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];
    private Throwable cause = this;
    private StackTraceElement[] stackTrace = UNASSIGNED_STACK;
    private transient int depth;
    private static final List<Throwable> SUPPRESSED_SENTINEL = Collections.emptyList();
    private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
    private static final String NULL_CAUSE_MESSAGE = “Cannot suppress a null exception.”;
    private static final String SELF_SUPPRESSION_MESSAGE = “Self-suppression not permitted”;
    private static final String CAUSE_CAPTION = “Caused by: “;
    private static final String SUPPRESSED_CAPTION = “Suppressed: “;
    /************* コンストラクタ ************************************/
    public Throwable() {
        fillInStackTrace();
    }
    public Throwable(String message) {
        fillInStackTrace();
        detailMessage = message;
    }
    public Throwable(String message, Throwable cause) {
        fillInStackTrace();
        detailMessage = message;
        this.cause = cause;
    }
    public Throwable(Throwable cause) {
        fillInStackTrace();
        detailMessage = (cause==null ? null : cause.toString());
        this.cause = cause;
    }
    protected Throwable(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace) {
        if (writableStackTrace) {
            fillInStackTrace();
        } else {
            stackTrace = null;
        }
        detailMessage = message;
        this.cause = cause;
        if (!enableSuppression)
            suppressedExceptions = null;
    }
    /***********************************************************************/
    
    
    
    public String getMessage() {
        return detailMessage;
    }
    public String getLocalizedMessage() {
        return getMessage();
    }
    public synchronized Throwable getCause() {
        return (cause==this ? null : cause);
    }
    public synchronized Throwable initCause(Throwable cause) {
        if (this.cause != this)
            throw new IllegalStateException(“Can’t overwrite cause with ” +
                                            Objects.toString(cause, “a null”), this);
        if (cause == this)
            throw new IllegalArgumentException(“Self-causation not permitted”, this);
        this.cause = cause;
        return this;
    }
    final void setCause(Throwable t) {
        this.cause = t;
    }
    public String toString() {
        String s = getClass().getName();
        String message = getLocalizedMessage();
        return (message != null) ? (s + “: ” + message) : s;
    }
    public void printStackTrace() {
        printStackTrace(System.err);
    }
    public void printStackTrace(PrintStream s) {
        printStackTrace(new WrappedPrintStream(s));
    }
    private void printStackTrace(PrintStreamOrWriter s) {
        Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
        dejaVu.add(this);
        synchronized (s.lock()) {
            s.println(this);
            StackTraceElement[] trace = getOurStackTrace();
            for (StackTraceElement traceElement : trace)
                s.println(“\tat ” + traceElement);
            for (Throwable se : getSuppressed())
                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, “\t”, dejaVu);
            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, “”, dejaVu);
        }
    }
    private void printEnclosedStackTrace(PrintStreamOrWriter s,
                                         StackTraceElement[] enclosingTrace,
                                         String caption,
                                         String prefix,
                                         Set<Throwable> dejaVu) {
        assert Thread.holdsLock(s.lock());
        if (dejaVu.contains(this)) {
            s.println(“\t[CIRCULAR REFERENCE:” + this + “]”);
        } else {
            dejaVu.add(this);
            StackTraceElement[] trace = getOurStackTrace();
            int m = trace.length – 1;
            int n = enclosingTrace.length – 1;
            while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
                m–; n–;
            }
            int framesInCommon = trace.length – 1 – m;
            s.println(prefix + caption + this);
            for (int i = 0; i <= m; i++)
                s.println(prefix + “\tat ” + trace[i]);
            if (framesInCommon != 0)
                s.println(prefix + “\t… ” + framesInCommon + ” more”);
            for (Throwable se : getSuppressed())
                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
                                           prefix +”\t”, dejaVu);
            Throwable ourCause = getCause();
            if (ourCause != null)
                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
        }
    }
    public void printStackTrace(PrintWriter s) {
        printStackTrace(new WrappedPrintWriter(s));
    }
    private abstract static class PrintStreamOrWriter {
        abstract Object lock();
        abstract void println(Object o);
    }
    private static class WrappedPrintStream extends PrintStreamOrWriter {
        private final PrintStream printStream;
        WrappedPrintStream(PrintStream printStream) {
            this.printStream = printStream;
        }
        Object lock() {
            return printStream;
        }
        void println(Object o) {
            printStream.println(o);
        }
    }

    private static class WrappedPrintWriter extends PrintStreamOrWriter {
        private final PrintWriter printWriter;

        WrappedPrintWriter(PrintWriter printWriter) {
            this.printWriter = printWriter;
        }

        Object lock() {
            return printWriter;
        }

        void println(Object o) {
            printWriter.println(o);
        }
    }
    public synchronized Throwable fillInStackTrace() {
        if (stackTrace != null ||
            backtrace != null /* Out of protocol state */ ) {
            fillInStackTrace(0);
            stackTrace = UNASSIGNED_STACK;
        }
        return this;
    }
    private native Throwable fillInStackTrace(int dummy);
    public StackTraceElement[] getStackTrace() {
        return getOurStackTrace().clone();
    }

    private synchronized StackTraceElement[] getOurStackTrace() {
        if (stackTrace == UNASSIGNED_STACK ||
            (stackTrace == null && backtrace != null) /* Out of protocol state */) {
            stackTrace = StackTraceElement.of(this, depth);
        } else if (stackTrace == null) {
            return UNASSIGNED_STACK;
        }
        return stackTrace;
    }
    public void setStackTrace(StackTraceElement[] stackTrace) {
        StackTraceElement[] defensiveCopy = stackTrace.clone();
        for (int i = 0; i < defensiveCopy.length; i++) {
            if (defensiveCopy[i] == null)
                throw new NullPointerException(“stackTrace[” + i + “]”);
        }
        synchronized (this) {
            if (this.stackTrace == null && // Immutable stack
                backtrace == null) // Test for out of protocol state
                return;
            this.stackTrace = defensiveCopy;
        }
    }
    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        s.defaultReadObject();     // read in all fields
        if (suppressedExceptions != null) {
            List<Throwable> suppressed = null;
            if (suppressedExceptions.isEmpty()) {
                // Use the sentinel for a zero-length list
                suppressed = SUPPRESSED_SENTINEL;
            } else { // Copy Throwables to new list
                suppressed = new ArrayList<>(1);
                for (Throwable t : suppressedExceptions) {
                    // Enforce constraints on suppressed exceptions in
                    // case of corrupt or malicious stream.
                    Objects.requireNonNull(t, NULL_CAUSE_MESSAGE);
                    if (t == this)
                        throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
                    suppressed.add(t);
                }
            }
            suppressedExceptions = suppressed;
        } // else a null suppressedExceptions field remains null
        if (stackTrace != null) {
            if (stackTrace.length == 0) {
                stackTrace = UNASSIGNED_STACK.clone();
            }  else if (stackTrace.length == 1 &&
                        // Check for the marker of an immutable stack trace
                        SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
                stackTrace = null;
            } else { // Verify stack trace elements are non-null.
                for(StackTraceElement ste : stackTrace) {
                    Objects.requireNonNull(ste, “null StackTraceElement in serial stream.”);
                }
            }
        } else {
            stackTrace = UNASSIGNED_STACK.clone();
        }
    }
    private synchronized void writeObject(ObjectOutputStream s)
        throws IOException {
        getOurStackTrace();

        StackTraceElement[] oldStackTrace = stackTrace;
        try {
            if (stackTrace == null)
                stackTrace = SentinelHolder.STACK_TRACE_SENTINEL;
            s.defaultWriteObject();
        } finally {
            stackTrace = oldStackTrace;
        }
    }
    public final synchronized void addSuppressed(Throwable exception) {
        if (exception == this)
            throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE, exception);
        Objects.requireNonNull(exception, NULL_CAUSE_MESSAGE);
        if (suppressedExceptions == null) // Suppressed exceptions not recorded
            return;
        if (suppressedExceptions == SUPPRESSED_SENTINEL)
            suppressedExceptions = new ArrayList<>(1);
        suppressedExceptions.add(exception);
    }
    private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
    public final synchronized Throwable[] getSuppressed() {
        if (suppressedExceptions == SUPPRESSED_SENTINEL ||
            suppressedExceptions == null)
            return EMPTY_THROWABLE_ARRAY;
        else
            return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
    }
}