• String类


    String类构造方法的部分源码

    package java.lang;
    
    import java.io.ObjectStreamField;
    import java.io.UnsupportedEncodingException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Formatter;
    import java.util.Locale;
    import java.util.Objects;
    import java.util.StringJoiner;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import java.util.regex.PatternSyntaxException;
    
    /**
     * {@code String} 类表示字符串。所有java程序中的字符串,如{@code "abc"},是作为该类的实例实现。
     * <p>字符串是常量,它们的值在它们之后不能改变。创建。字符串缓冲区支持可变字符串。因为字符串对象是不可变的,所以它们可以被共享。例如:
     * <blockquote><pre>
     *     String str = "abc";
     * </pre></blockquote><p>
     * 相当于:
     * <blockquote><pre>
     *     char data[] = {'a', 'b', 'c'};
     *     String str = new String(data);
     * </pre></blockquote><p>
     * 下面是一些字符串如何使用的例子:
     * <blockquote><pre>
     *     System.out.println("abc");
     *     String cde = "cde";
     *     System.out.println("abc" + cde);
     *     String c = "abc".substring(2,3);
     *     String d = cde.substring(1, 2);
     * </pre></blockquote>
     * <p>
     * String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。
     * 大小写映射基于 Character 类指定的 Unicode 标准版。 
     * <p>
     * Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。
     * 字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。有关字符串串联和转换的更多信息,请参阅 Gosling、Joy和
     * Steele合著的 The Java Language Specification。 
     * <i>java语言规范</i>.
     *
     * <p> 除非另行说明,否则将 null 参数传递给此类中的构造方法或方法将抛出 NullPointerException。 
     *
     * <p>String 表示一个 UTF-16 格式的字符串,其中的增补字符 由代理项对 表示(有关详细信息,请参阅 Character 类中的 Unicode 字符表示形式)。
     * 索引值是指 char 代码单元,因此增补字符在 String 中占用两个位置。 
     * <p>String 类提供处理 Unicode 代码点(即字符)和 Unicode 代码单元(即 char 值)的方法。 
     *
     * @author  Lee Boynton
     * @author  Arthur van Hoff
     * @author  Martin Buchholz
     * @author  Ulf Zibis
     * @see     java.lang.Object#toString()
     * @see     java.lang.StringBuffer
     * @see     java.lang.StringBuilder
     * @see     java.nio.charset.Charset
     * @since   JDK1.0
     */
    
    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        /** 该值用于字符存储。 */
        private final char value[];
    
        /** 字符串缓存的哈希代码 */
        private int hash; // Default to 0
      
        private static final long serialVersionUID = -6849794470754667710L;
        
        private static final ObjectStreamField[] serialPersistentFields =
            new ObjectStreamField[0];
        
        /**
         * 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。由于 String 是不可变的,
         * 所以无需使用此构造方法,除非需要 original 的显式副本。 
         *
         * @param  original 一个 String。 
         */
        public String(String original) {
            this.value = original.value;
            this.hash = original.hash;
        }
    
        /**
         * 分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。该字符数组的内容已被复制;后续对字符数组的修改不会影响新创建的字符串。 
         * @param  value 字符串的初始值 
         */
        public String(char value[]) {
            this.value = Arrays.copyOf(value, value.length);
        }
    
        /**
         * 分配一个新的 String,它包含取自字符数组参数一个子数组的字符。 offset 参数是子数组第一个字符的索引, count 参数指定子数组的长度。该子数组的内容已
         * 被复制;后续对字符数组的修改不会影响新创建的字符串。 
         *
         * @param  value 作为字符源的数组。
         *
         * @param  offset 初始偏移量。
         *
         * @param  count 长度。 
         *
         * @throws  IndexOutOfBoundsException  如果 offset 和 count 参数索引字符超出 value 数组的范围。 
         */
        public String(char value[], int offset, int count) {
            if (offset < 0) {
                throw new StringIndexOutOfBoundsException(offset);
            }
            if (count <= 0) {
                if (count < 0) {
                    throw new StringIndexOutOfBoundsException(count);
                }
                if (offset <= value.length) {
                    this.value = "".value;
                    return;
                }
            }
            // offset 或 count 也许  -1>>>1.
            if (offset > value.length - count) {
                throw new StringIndexOutOfBoundsException(offset + count);
            }
            this.value = Arrays.copyOfRange(value, offset, offset+count);
        }
        
        private static void checkBounds(byte[] bytes, int offset, int length) {
            if (length < 0)
                throw new StringIndexOutOfBoundsException(length);
            if (offset < 0)
                throw new StringIndexOutOfBoundsException(offset);
            if (offset > bytes.length - length)
                throw new StringIndexOutOfBoundsException(offset + length);
        }
    
        /**
         * 通过使用指定的字符集解码指定的 byte 子数组,构造一个新的 String。新 String 的长度是一个字符集函数,因此可能不等于子数组的长度。
         *  
         *
         * <p> 当给定 byte 在给定字符集中无效的情况下,此构造方法的行为没有指定。如果需要对解码过程进行更多控制,则应该使用 CharsetDecoder 类。
         *
         * @param  bytes 要解码为字符的 byte 
         *
         * @param  offset 要解码的第一个 byte 的索引 
         *
         * @param  length 要解码的 byte 数 
    
         * @param  charsetName 受支持 charset 的名称 
         *
         * @throws  如果指定的字符集不受支持 
         *
         * @throws  IndexOutOfBoundsException 如果 offset 和 length 参数索引字符超出 bytes 数组的范围 
         *
         * @since  JDK1.1
         */
        public String(byte bytes[], int offset, int length, String charsetName)
                throws UnsupportedEncodingException {
            if (charsetName == null)
                throw new NullPointerException("charsetName");
            checkBounds(bytes, offset, length);
            this.value = StringCoding.decode(charsetName, bytes, offset, length);
        }
    
        /**
         * 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。新 String 的长度是字符集的函数,因此可能不等于 byte 数组的长度。 
         *
         * <p>当给定 byte 在给定字符集中无效的情况下,此构造方法的行为没有指定。如果需要对解码过程进行更多控制,则应该使用 CharsetDecoder 类。
         *
         * @param  bytes 要解码为字符的 byte 
         *
         * @param  charsetName 受支持的 charset 的名称 
         *
         * @throws  UnsupportedEncodingException 如果指定字符集不受支持 
         *
         * @since  JDK1.1
         */
        public String(byte bytes[], String charsetName)
                throws UnsupportedEncodingException {
            this(bytes, 0, bytes.length, charsetName);
        }
        /**
         *  通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。新 String 的长度是字符集的函数,因此可能不等于该子数组的长度。 
         *
         * <p>当给定 byte 在给定字符集中无效的情况下,此构造方法的行为没有指定。如果需要对解码过程进行更多控制,则应该使用 CharsetDecoder 类。 
         *
         * @param  bytes 要解码为字符的 byte 
         *
         * @param  offset  要解码的第一个 byte 的索引 
         *
         * @param  length  要解码的 byte 数 
         *
         * @throws  IndexOutOfBoundsException 如果 offset 和 length 参数索引字符超出 bytes 数组的范围 
         *
         * @since  JDK1.1
         */
        public String(byte bytes[], int offset, int length) {
            checkBounds(bytes, offset, length);
            this.value = StringCoding.decode(bytes, offset, length);
        }
    
        /**
         * 通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。新 String 的长度是字符集的函数,因此可能不等于 byte 数组的长度。 
         *
         * <p> 当给定 byte 在给定字符集中无效的情况下,此构造方法的行为没有指定。如果需要对解码过程进行更多控制,则应该使用 CharsetDecoder 类。 
         *
         * @param  bytes 要解码为字符的 byte 
         *
         * @since  JDK1.1
         */
        public String(byte bytes[]) {
            this(bytes, 0, bytes.length);
        }
    
        /**
         * 分配一个新的字符串,它包含字符串缓冲区参数中当前包含的字符序列。该字符串缓冲区的内容已被复制,后续对它的修改不会影响新创建的字符串。 
         *
         * @param  buffer 一个 StringBuffer
         */
        public String(StringBuffer buffer) {
            synchronized(buffer) {
                this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
            }
        }
    
        /**
         * 分配一个新的字符串,它包含字符串生成器参数中当前包含的字符序列。该字符串生成器的内容已被复制,后续对它的修改不会影响新创建的字符串。 
         *
         * <p>提供此构造方法是为了简化到 StringBuilder 的迁移。通过 toString 方法从字符串生成器中获取字符串可能运行的更快,因此通常作为首选。 
         *
         * @param   builder  一个 StringBuilder
         *
         * @since  1.5
         */
        public String(StringBuilder builder) {
            this.value = Arrays.copyOf(builder.getValue(), builder.length());
        }
    }

    源码理解

    String类位于java.lang包下实现了Comparable和Serializable接口,因此可以序列化,可以进行比较,并且String类是被final修饰,因此不能被继承,并且该类中的成员默认final方法。String类中包含一个不可变的char数组用来存放字符串,一个int型的变量hash用来存放计算后的哈希值,因此String类本质是char数组。使用 byte[] 构造 String时可以指定解码使用的字符集,默认是ISO-8859-1 编码格式进行编码操作。

    字符集测试案例

    package ecut.strings;
    
    import java.nio.charset.Charset;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    /**
     *  Java支持的字符集。
     *  常用字符编码:
     *  UTF-8 ( Unicode 的子集 )
     *  GBK ( GB2312 / GB18030 ) 中国大陆采用的简体汉字编码 
     *  Big5 繁体中文 (正体中文)
     *  ISO-8859-1
     */
    public class CharsetTest {
    
        public static void main(String[] args) {
            //构造从规范 charset 名称到 charset 对象的有序映射。
            Map<String,Charset> map = Charset.availableCharsets();
            
            // 迭代 map 返回此映射中包含的键的 Set 视图。
            Set<String> keys = map.keySet();
            
            // foreach 循环中 可以处理的 对象有 数组 或 java.lang.Iterable 接口的实现类
            for( String key : keys ) {
                //返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
                Charset value = map.get( key );
                System.out.println( key + " : " + value );
            }
            
            //返回在此 set 中的元素上进行迭代的迭代器。
            Iterator<String> it =  keys.iterator();
            
            while( it.hasNext() ) {
                String key = it.next();
                Charset value = map.get( key ); // 根据 key 取出 value
                System.out.println( key + " : " + value );
            } 
    
        }
    
    }

    运行结果如下:

    Big5 : Big5
    Big5-HKSCS : Big5-HKSCS
    CESU-8 : CESU-8
    ......
    x-windows-949 : x-windows-949 x-windows-950 : x-windows-950 x-windows-iso2022jp : x-windows-iso2022jp

    String类创建方式

    1、双引号型

    2、new型

    package ecut.strings;
    
    public class StringTest1 {
    
        public static void main(String[] args) {
            
            // 所有的 "" 包起来的 字符串 字面值一律放在 字符串常量池中
            //去字符串常量池池寻找相同内容的字符串,如果存在就直接拿出来应用,如果不存在则创建一个新的字符串放在常量池中。
            String s = "hello,ecut" ;
            System.out.println( System.identityHashCode( s ) );
            //通过 new关键字创建 String 对象,每次调用都会创建一个新的对象。
            String x = new String( "hello,ecut" );
            System.out.println( System.identityHashCode( x ) );
            
            System.out.println( s == x );
            
            // 返回字符串对象的规范化表示形式
            // 如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。
            // 否则,将此 String 对象添加到池中,并返回此 String 对象的引用(加入到池中以后的那个串的地址)
            String str = x.intern();
            System.out.println( System.identityHashCode( str ) );
            
            System.out.println( str == s );
            
            
        }
    
    }

    运行结果如下:

    366712642
    1829164700
    false
    366712642
    true

    从结果可以看出s和x的地址是不相等的,是因为String s = "hello,ecut", 首先在常量池中查找是否存在内容为"hello,ecut"字符串对象,如果不存在则在常量池中创建"hello,ecut",并让s引用该对象(12345),如果存在则直接让s引用该对象,而new String( "hello,ecut" )时会在堆中创建一个对象ABCDE,并由栈中x引用堆中的ABCDE对象,然后在在字符串常量池中查看,是否存在内容为"hello,ecut"字符串对象,若存在,则将new出来的字符串对象与字符串常量池中的对象(12345)联系起来若不存在,则在字符串常量池中创建一个内容为"hello,ecut"的字符串对象,并将堆中的对象与之联系起来。x.intern()方法则是如果池已经包含一个等于此 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串,否则,将此 String 对象添加到池中,并返回此 String 对象的引用(加入到池中以后的那个串的地址)。因此str和s地址相同。

     ==比较的是2个对象的地址,而equals比较的是2个对象的内容。

    package ecut.strings;
    
    public class StringTest2 {
    
        public static void main(String[] args) {
            
            final char[] chars = { '春' , '眠' , '不' , '觉' , '晓' };
            System.out.println( "chars: " + System.identityHashCode( chars ) );
            
            String s = new String( chars );
            System.out.println( "s : " + System.identityHashCode( s ) );
            
            System.out.println( s );
            
            String x = s.intern(); // 返回规范化表示形式
            
            System.out.println( "s.intern : " + System.identityHashCode( x ) );
            
            System.out.println( s == x ); // true
            
            String r = "春眠不觉晓";
            System.out.println( s == r );
            
        }
    
    }

    运行结果如下:

    chars: 366712642
    s : 1829164700
    春眠不觉晓
    s.intern : 1829164700
    true
    true
    

    从结果可以看出s和r的地址是相等的,r调用的是String类的无参构造函数,根据源码this.value = "".value;其中value定义private final char[]创建一个空串并将它的值放在数组value中,s调用的构造方法是使用字符数组的有参构造,根据源码this.value = Arrays.copyOf(value,value.length)是将传入的字符数组拷贝到数组value中。因此String r = "春眠不觉晓";和 final char[] chars = { '春' , '眠' , '不' , '觉' , '晓' }; String s = new String( chars );是等价的。

    package ecut.strings;
    
    public class StringTest3 {
    
        public static void main(String[] args) {
            
            String r = "春眠不觉晓";
            System.out.println( "r : " + System.identityHashCode( r ) );
            
            final char[] chars = { '春' , '眠' , '不' , '觉' , '晓' };
            
            String s = new String( chars );
            System.out.println( "s : " + System.identityHashCode( s ) );
            
            String x = s.intern(); 
            System.out.println( "x : " + System.identityHashCode( x ) );
            
        }
    
    }

    运行结果如下:

    r : 366712642
    s : 1829164700
    x : 366712642

    栈:运行时的单位,存放基本类型的变量数据和对象的引用,栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。

    堆:存储的单位,用于存放所以的JAVA对象,堆解决的是数据存储的问题,即数据怎么放、放在哪儿。

    常量池:存放字符串常量和基本类型常量(public static final)

    使用字节数组构造String测试案例:

    package ecut.strings;
    
    import java.util.Arrays;
    
    //  对于中文来说 UTF-8 编码可以是 2~3 个字节 (大部分都是3个字节)
    public class StringTest4 {
    
        public static void main(String[] args) throws Exception {
            
            String s = "今天天气孬abc" ;
            System.out.println( s.length() );
        
            // byte[] bytes = s.getBytes(); // 采用默认编码
            byte[] bytes = s.getBytes( "UTF-8" );
            
            System.out.println( Arrays.toString( bytes ) );
            System.out.println( bytes.length );
            
            // String x = new String( bytes );
            String x = new String( bytes , "UTF-8");
            System.out.println( x );
            
        }
    
    }

    运行结果如下:

    8
    [-28, -69, -118, -27, -92, -87, -27, -92, -87, -26, -80, -108, -27, -83, -84, 97, 98, 99]
    18
    今天天气孬abc

    字符串联的方式

    测试案例:

    package ecut.strings;
    
    /**
     * 当 字符串 变量 参与 串联 操作时
     * 是通过 StringBuilder ( 或 StringBuffer ) 类及其 append 方法实现的
     */
    public class StringTest5 {
    
        public static void main(String[] args) {
            
            String a = "abc" ;
            String b = "xyz";
            
            String d = "abcxyz" ;
            // 两个字符串字面值 通过 + 串联,直接在 池中完成
            String c = "abc" + "xyz" ; // + 是 "串联" 作用
    
            System.out.println( c == d );
            
            System.out.println( "~~~~~~~~~~~~~~" );
            
            // 字符串串联是通过 StringBuilder ( 或 StringBuffer ) 类及其 append 方法实现的
            // 1、StringBuilder sb = new StringBuilder( a );
            // 2、sb.append( b ) ;
            // 3、sb.toString() ---> new String( chars )
            String e = a + b ;
            System.out.println( e == c );
            System.out.println( e == d );
            
            String f = e.intern();
            
            System.out.println( f == d );
            //JAVA编译器对string + 基本类型/常量 是当成常量表达式直接求值来优化的。  运行期的两个string相加,会产生新的对象的,存储在堆(heap)中 
            String g = a + "xyz" ;//a为变量,在运行期才会被解析。 
            System.out.println( g == c );
            
            final String h = "abc" ;
            String i = h + "xyz" ;
            System.out.println( i == c );//h为常量,编译期会被优化  
            
        }
    
    }

    运行结果如下:

    true
    ~~~~~~~~~~~~~~
    false
    false
    true
    false
    true

    String常用方法

     测试案例:

    package ecut.strings;
    
    import java.nio.charset.Charset;
    import java.util.Arrays;
    
    /**
     */
    public class StringTest6 {
    
        public static void main(String[] args) {
            
            String s = "How old are you ? " ;
            System.out.println("1、求字符串长度");
            int len = s.length();
            System.out.println("字符串的长度"+len);
            System.out.println("2、求字符串某一位置字符");
            char ch = s.charAt(2);//索引范围为从 0 到 length() - 1。
            System.out.println("字符串第2+1个字符是"+ch);
            System.out.println("3、提取子串");
            String s1 = s.substring(2, 5);//beginIndex - 起始索引(包括) endIndex - 结束索引(不包括)。 
            String s2 = s.substring(18);//beginIndex 大于0小于等于String对象的长度,等于时返回空串。 
            System.out.println("子串s1为:"+s1);
            System.out.println("子串s2为"+s2);
            System.out.println("4、字符串比较");
            String str1 = new String("abc");
            String str2 = new String("ABC");
            int a = str1.compareTo(str2);//若当前对象比参数大则返回正整数,反之返回负整数,相等返回0。
            int b = str1.compareToIgnoreCase(str2);//忽略大小写
            System.out.println("若当前对象比参数大则返回正整数,反之返回负整数,相等返回0");
            boolean c = str1.equals(str2);//c=false
            boolean d = str1.equalsIgnoreCase(str2);//d=true
            System.out.println("比较当前字符串和参数字符串,在两个字符串相等的时候返回true,否则返回false。");
            System.out.println("5、字符串中单个字符查找");
            int in = s.indexOf('y');
            System.out.println("字符串中y的位置"+in);
            System.out.println("6、字符串中字符的大小写转换");
            String str3 = s.toLowerCase();
            String str4 = s.toUpperCase();
            System.out.println("转换为小写为"+str3);
            System.out.println("转换为大写为"+str4);
            System.out.println("7、字符串中字符的替换");
            String str5 = s.replace('o', 'a');
            System.out.println("a替换o后为"+str5);
            System.out.println("8、字符串连接");
            String str6 = s.concat(str1);
            System.out.println("str1和s连接后为"+str6);
            System.out.println("9、截去字符串两端的空格");
            String str7 = s.trim();
            System.out.println("s截去字符串两端的空格,但对于中间的空格不处理后为"+str7);
            System.out.println("10、比较起始字符或结尾字符是否一致");
            s.startsWith("a");
            System.out.println("用来比较当前字符串的起始字符或子字符串prefix和终止字符或子字符串suffix是否和当前字符串相同,重载方法中同时还可以指定比较的开
    始位置offset。"); System.out.println("11、作为分隔符进行字符串分解"); String[] str8 = s.split(" "); for( String str : str8 ) { System.out.println(str); } System.out.println("12、判断是否包含字符串"); s.contains("ow"); System.out.println("判断参数是否被包含在字符串中,并返回一个布尔类型的值。"); System.out.println("13、字符串转换为基本类型"); int e = Integer.parseInt("12"); float f = Float.parseFloat("12.34"); double g = Double.parseDouble("1.124"); System.out.println("e="+e+",f="+f+",g="+g); System.out.println("14、基本类型转换为字符串"); String str9 = String.valueOf(12); System.out.println("str9为"+str9); System.out.println("15、将字符从此字符串复制到目标字符数组。 "); char[] chars = new char[ 10 ]; System.out.println( chars[ 0 ] == 'u0000' ); // 将字符串中的 [ 4 , 7 )之间的字符 复制到 chars 数组的下标是5的位置开始 s.getChars( 4 , 7 , chars , 5 );// getChars()方法,不是返回一个数组,而是复制数组
    System.out.println("将字符串中的 [ 4 , 7 )之间的字符 复制到 chars 数组的下标是5的位置开始 "); System.out.println( Arrays.toString( chars ) ); } }
    
    
    
    
    

    运行结果如下:

    1、求字符串长度
    字符串的长度18
    2、求字符串某一位置字符
    字符串第2+1个字符是w
    3、提取子串
    子串s1为:w o
    子串s2为
    4、字符串比较
    若当前对象比参数大则返回正整数,反之返回负整数,相等返回0
    比较当前字符串和参数字符串,在两个字符串相等的时候返回true,否则返回false。
    5、字符串中单个字符查找
    字符串中y的位置12
    6、字符串中字符的大小写转换
    转换为小写为how old are you ? 
    转换为大写为HOW OLD ARE YOU ? 
    7、字符串中字符的替换
    a替换o后为Haw ald are yau ? 
    8、字符串连接
    str1和s连接后为How old are you ? abc
    9、截去字符串两端的空格
    s截去字符串两端的空格,但对于中间的空格不处理后为How old are you ?
    10、比较起始字符或结尾字符是否一致
    用来比较当前字符串的起始字符或子字符串prefix和终止字符或子字符串suffix是否和当前字符串相同,重载方法中同时还可以指定比较的开始位置offset。
    11、作为分隔符进行字符串分解
    How
    old
    are
    you
    ?
    12、判断是否包含字符串
    判断参数是否被包含在字符串中,并返回一个布尔类型的值。
    13、字符串转换为基本类型
    e=12,f=12.34,g=1.124
    14、基本类型转换为字符串
    str9为12
    15、将字符从此字符串复制到目标字符数组。 
    true
    将字符串中的 [ 4 , 7 )之间的字符 复制到 chars 数组的下标是5的位置开始 
    [

    StringBuffer和StringBuilder

    1、StringBuffer

    package ecut.strings;
    
    public class StringBufferTest {
    
        public static void main(String[] args) {
            
            // s.value ==>  "abc".value ;
            // String s = "abcxyz";
            
            
            // char[] value = new char[ 3 + 16 ];
            // value[ 0 ] = 'a' ;  value[ 1 ] = 'b' ;  value[ 2 ] = 'c' ;
            StringBuffer sb = new StringBuffer( "abc" ); 
            
            // value[ 3 ] = 'x' ;  value[ 4 ] = 'y' ;  value[ 5 ] = 'z' ;
            sb.append( "xyz" );
            
            String x = sb.toString() ; 
            System.out.println( x );
            //返回字符串对象的规范化表示形式。
            String y = x.intern();
            
            System.out.println( x == y );
            
            System.out.println( "~~~~~~~~~~~~~~~~~~~~~~~~" );
            
            // 池中有几个串
            // "a"
            // "ab"
            // "abc"
            // "abcd"
            // "abcde"
            String str = "a" + "b" + "c" + "d" + "e" ;
            System.out.println( str );
            
            StringBuffer buffer = new StringBuffer();
            buffer.append( "a" );
            buffer.append( "b" );
            buffer.append( "c" );
            buffer.append( "d" );
            buffer.append( "e" );
            
            String r = buffer.toString();
            System.out.println( r );
    
        }
    
    }

    运行结果如下:

    abcxyz
    true
    ~~~~~~~~~~~~~~~~~~~~~~~~
    abcde
    abcde

    2、StringBuilder

    package ecut.strings;
    
    public class StringBuilderTest {
    
        public static void main(String[] args) {
            
            StringBuilder builder = new StringBuilder();
            
            builder.append( "a" );
            builder.append( "b" );
            builder.append( "c" );
            builder.append( "d" );
            builder.append( "e" );
            
            System.out.println( builder );
            
            String r = builder.toString();
            System.out.println( r );
            //将此字符序列用其反转形式取代
            builder.reverse();
            
            System.out.println( builder );
    
        }
    
    }

    运行结果如下:

    abcde
    abcde
    edcba

    String、StringBuffer和StringBuilder区别
    String 是被 final 修饰的,他的长度是不可变的,就算调用 String 的concat 方法,那也是把字符串拼接起来并重新创建一个对象,把拼接后的 String 的值赋给新创建的对象,而 StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象,调用StringBuffer 的 append 方法,来改变 StringBuffer 的长度,并且,相比较于 StringBuffer,String 一旦发生长度变化,是非常耗费内存的!StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。 append方法与直接使用+串联相比,减少常量池的浪费。

    待解决问题

    两幅图结果为什么不一样

    参考博客链接

    http://blog.csdn.net/ithomer/article/details/9936743

    https://www.cnblogs.com/ITtangtang/p/3976820.html

    转载请于明显处标明出处

    http://www.cnblogs.com/AmyZheng/p/8453374.html

  • 相关阅读:
    8.14 每日课后作业系列之RE正则 模块的运用
    8.13 每日课后作业系列之hashlib shelve xml模块的运用
    8.10 每日课后作业系列之包的建立
    8.9 每日课后作业系列之进度条 and 验证码
    操作系统与python入门
    计算机硬件基础
    MySQL系列
    html5和css (四 布局新增)
    html5和css(三 页面布局)
    html5和css(二 页面组成)
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/8453374.html
Copyright © 2020-2023  润新知