- 接口
- 字符编码
- 字符集
- 类
- 理解字符编码对字符串的影响">理解字符编码对字符串的影响
- getChars/toCharArray/使用+运算符连接字符串">getChars/toCharArray/使用+运算符连接字符串
- String类中常用实例方法:intern">String类中常用实例方法:intern
- 使用CharacterStrings实现CharSequence">使用CharacterStrings实现CharSequence
- 理解StringBuffer实例的可变性、测试常用的方法:append / insert / replace">理解StringBuffer实例的可变性、测试常用的方法:append / insert / replace
- 了解StringBuffer内部的一些方法是返回当前的StringBuffer对象">了解StringBuffer内部的一些方法是返回当前的StringBuffer对象
- 通过StringBuilder实例测试setLength和trimToSize">通过StringBuilder实例测试setLength和trimToSize
接口
java.lang.CharSequence
java.lang.Comparable
java.lang.Appendable
字符编码
理解编码
编码(encode)
将字符串按照某种字符集 转换成字节序列
比如”中国”按照”UTF-8”转换为{-28,-72,-83,-27,-101,-67}
解码(decode)
将字节序列按照字符集转化成字符串
比如:{-28,-72,-83,-27,-101,-67}按照”UTF-8”转换为中国
字符集
常用字符集
ISO-8859-1
Latin1
Big-5:繁体中文
GBK:简体中文 每个字符占两个字符
UTF-8 每个字符占1~4个字节
Unicode
范围是U+0000-U+10FFFF
Java语言中char类型的范围是U+0000~U+FFFF
UTF-8
UTF-8是Unicode的一种可变长度字符编码
将字符串从中的字符编码为字节序列后,每个字符占1~4个字节
汉字基本都占三个字节
UTF-16
UTF-16
UTF-16BE
UTF-16LE
UTF-32
UTF-32
UTF-32BE
UTF-32LE
类
Java.lang.String
意义
String是个类,character string才是字符串
String 类实例表示character string(字符串)
实例变量
private final byte[] value;
private final byte coder;
private int hash
构造方法
public String (byte【】 bytes)
public String(byte【】 bytes,int offset,int length)
public String (byte【】 bytes,Charset charset)
public String(byte【】 bytes,int offset,int length,,Charset charset)
实例方法
public byte[] getByte()
public byte[] getByte(Charset charset) 以指定的字符集编码如s.getByte(UTF-8)
public byte[] getByte(String charsetName)
类变量
static final byte LATIN1=0;
static final byte UTF-16=1;
static final boolean COMPACT_STRINGS;
类方法
java.lang.AbstractString
它是java.lang包中一个没有public修饰的类
从JDK5开始提供
实例变量
byte[]value;
byte coder;
int count;
java.lang.StringBuffer
线程安全的
所有的public方法都是synchronized修饰的
private transient String toStringCache
java.lang.StringBuilder
线程不安全
所有的public方法都没有synchronized修饰的
java.nio.charset.Charset
抽象类Charset的实例表示字符集
public static Charset defaultCharset()
public static boolean isSupported(String charsetName)
public static Charset forName(String charsetName)
理解字符编码对字符串的影响
import java.nio.charset.Charset;
import java.util.Arrays;
/
1、获取指定字符串对应的字节序列: getBytes()
2、将一组字节序列编码为一个字符串: String( byte[] ) 、String( byte[] , int , int )
3、编码 : 将人类易读的字符串 转换为 一组字节序列 的过程
“中国” ===========》{ -28, -72, -83, -27, -101, -67 }
4、解码 : 将一组字节序列 转换为 人类易读的字符串 的过程
{ -28, -72, -83, -27, -101, -67 } ===========》”中国”
5、字符集: 从 JDK 1.4 开始 增加了 java.nio.charset.Charset 类表示字符集
/
pub**lic class StringTest6 {
public static void main(String[] args) {
**byte**[] bytes = { 97 , 98 , 99 , 100 , 101 , 102 , 48 , 49 , 50 , 51 , 52 , 53 };
// 通过使用 平台的默认字符集 解码 指定的 byte 数组,构造一个新的 String 实例<br /> **String** s = **new** **String**( bytes );<br /> **System**.out.println( s );//abcdef012345
**String** x = **new** **String**( bytes , 0 , 6 );<br /> **System**.out.println( x );//abcdef
bytes[ 0 ] = 65 ;
**System**.out.println( s );//abcdef012345<br /> **System**.out.println( x );//abcde
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**String** t = "中国" ;<br /> **System**.out.println( t );
// 使用 平台的默认字符集 将此 String 编码 为 byte 序列,并将结果存储到一个新的 byte 数组中<br /> **byte**[] bs = t.getBytes();<br /> // java.util 包 中的 Arrays 类的 toString 方法可以将 数组中的元素 链接到一个字符串中<br /> **String** u = **Arrays**.toString( bs );//[-28, -72, -83, -27, -101, -67]<br /> **System**.out.println( u );
**String** n = **new** **String**( bs );<br /> **System**.out.println( n );//中国
// String m = new String( new byte[]{ -28, -72, -83, -27, -101, -67 } ) ;
**byte**[] b = **new** **byte**[]{ -28, -72, -83, -27, -101, -67 } ;<br /> **String** m = **new** **String**( b ) ;<br /> **System**.out.println( m );//中国
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 获得 平台的默认字符集<br /> **Charset** defaultCharset = **Charset**.defaultCharset() ;<br /> **System**.out.println( defaultCharset );//UTF-8
}<br />}
/
1、常用字符集
GBK : 简体中文
全称《汉字内码扩展规范》(GBK即“国标”、“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Specification)
UTF-8 : 可以表示 西欧诸国字符 、东亚诸国字符 (但是不是全部)
8位元,Universal Character Set/Unicode Transformation Format)是针对 Unicode 的一种可变长度字符编码
ISO-8859-1 :
编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号
Latin1 :
Latin1 是ISO-8859-1的别名,有些环境下写作 Latin-1
Big 5 : 繁体中文(正体中文)
2、通过 Charset.forName( name ) 方法可以获得指定名称的字符集对应的 Charset 实例
3、根据指定的 字符集 将 字符串 编码为 字节序列
4、同一个字符串(尤其是东亚诸国字符)通过不同的字符集编码后的字节序列是不相同的
import java.nio.charset.Charset;
import java.util.Arrays;
public class StringTest7 {
public static void main(String**[] args) {
// 如果为 Charset.forName( name ) 指定的参数 ( 一个字符编码的名称) 是不被JVM支持的,<br /> // 则会抛出 ava.nio.charset.UnsupportedCharsetException<br /> **Charset** first = **Charset**.forName( "GBK" );<br /> **System**.out.println( first + " , " + first.getClass().getName() ); // 输出 字符串形式 和 运行时类型的名称
**Charset** second = **Charset**.forName( "UTF-8" );<br /> **System**.out.println( second + " , " + second.getClass().getName() );
**Charset** third = **Charset**.forName( "Big5" );<br /> **System**.out.println( third + " , " + third.getClass().getName() );
**Charset** fourth = **Charset**.forName( "ISO-8859-1" );<br /> **System**.out.println( fourth + " , " + fourth.getClass().getName() );
**Charset** fifth = **Charset**.forName( "Latin1" );<br /> **System**.out.println( fifth + " , " + fifth.getClass().getName() );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**String** s = "中国威武" ;
// 使用 平台的默认字符集 将此 String 编码 为 byte 序列,并将结果存储到一个新的 byte 数组中<br /> **byte**[] defaultBytes = s.getBytes();<br /> **System**.out.println( "默认的 : " + **Arrays**.toString( defaultBytes ) );//默认的 : [-28, -72, -83, -27, -101, -67, -27, -88, -127, -26, -83, -90]
// 使用给定的 charset 实例 将此 String 编码 为 byte 序列,并将结果存储到新的 byte 数组<br /> **byte**[] firstBytes = s.getBytes( first ); // GBK<br /> **System**.out.println( first + " : " + **Arrays**.toString( firstBytes ) );//GBK : [-42, -48, -71, -6, -51, -2, -50, -28]
**byte**[] secondBytes = s.getBytes( second ); // UTF-8<br /> **System**.out.println( second + " : " + **Arrays**.toString( secondBytes ) );//UTF-8 : [-28, -72, -83, -27, -101, -67, -27, -88, -127, -26, -83, -90]
**byte**[] thirdBytes = s.getBytes( third ); // Big5<br /> **System**.out.println( third + " : " + **Arrays**.toString( thirdBytes ) );//[-92, -92, 63, -85, -62, -86, 90]
**byte**[] fourthBytes = s.getBytes( fourth ); // ISO-8859-1<br /> **System**.out.println( fourth + " : " + **Arrays**.toString( fourthBytes ) );//ISO-8859-1 : [63, 63, 63, 63]
}<br />}
乱码问题
import java.nio.charset.Charset;
import java.util.Arrays;
public class StringTest8 {
public static void main(String[] args) {
**final** **String** s = "中国威武" ;<br /> **System**.out.println( s); // 正常
**Charset** first = **Charset**.forName( "GBK" ); // 每个汉字占两个字节<br /> **Charset** second = **Charset**.forName( "UTF-8" );
**byte**[] firstBytes = s.getBytes( first ); // 使用 GBK 字符集 将 字符串 编码 为 字节序列<br /> **System**.out.println( **Arrays**.toString( firstBytes ) );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**String** x = **new** **String**( firstBytes , second ); // 使用 指定的字符集 将 字节序列 解码 为 字符串<br /> **System**.out.println( x ); // 乱码
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**String** y = **new** **String**( firstBytes , first ); // 使用 指定的字符集 将 字节序列 解码 为 字符串<br /> **System**.out.println( y ); // 正常
}<br />}
String内部字符集是UTF-16LE
/
1、在 String 实例内部封装的 byte 数组中存储 是 字符串 按照 UTF-16LE字符集 编码后的字节序列
2、在通过 String 实例 的 getBytes 方法获取字节序列时,可以指定 任意字符集
3、将一组字节序列构成为 String 实例时,必须指定 将字符串编码为字节序列时 所采用的 字符集 才能保证不乱码
/
import java.nio.charset.Charset;
import java.util.Arrays**;
public class StringTest9 {
public static void main(String[] args) {
**final** **String** s = "中国威武" ;<br /> **StringHelper**.perspective( s );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**Charset** utf = **Charset**.forName( "UTF-16LE" ); // 16-bit
**byte**[] bytes = s.getBytes( utf ) ; // 使用 UTF-16LE 字符集 将 字符串中的字符 编码为 字节序列<br /> **System**.out.println( **Arrays**.toString( bytes ) );
**byte**[] array = { 45, 78, -3, 86, 1, 90, 102, 107 } ;<br /> **String** x = **new** **String**( array , utf ) ; // 使用 UTF-16LE 字符集 将 字节序列 解码为 字符串中的字符<br /> **System**.out.println( x );
}<br />}
String类中常用实例方法
/
1、 int length() 获取字符串长度 ( 字符串中所包含的字符个数 )
2、char charAt( int ) 获取指定索引处的单个字符
3、boolean contains( CharSequence ) 判断指定的 字符序列 是否存在于 当前字符串中,若存在即返回 true 否则返回 false
4、int indexOf( int ch ) 查询 指定字符 在 当前字符串中首次出现的位置,若存在即返回该索引,否则返回 -1
5、int indexOf( String s ) 查询 指定字符串 在 当前字符串中首次出现的位置,若存在即返回该索引,否则返回 -1
6、int lastIndexOf( int ch ) 查询 指定字符 在 当前字符串中最后一次出现的位置,若存在即返回该索引,否则返回 -1
7、int lastIndexOf( String s ) 查询 指定字符串 在 当前字符串中最后一次出现的位置,若存在即返回该索引,否则返回 -1
/
public class StringTestA {
public static void main(String**[] args) {
**final** **String** s = "今天天气好晴朗处处好风光好风光" ;<br /> **for**( **int** i = 0 , n = s.length() ; i < n ; i++ ) { // 【 int length() 】<br /> **char** ch = s.charAt( i ); // 【 char charAt( int ) 】<br /> **System**.out.print( ch );<br /> **System**.out.print( i < n - 1 ? " , " : "\n" );<br /> }
// 因为 String 类实现了 CharSequence 接口<br />**CharSequence** cs = "好风光" ; // 所以用 CharSequence 类型的引用变量 指向 String 实例是可以的,也可以用<br />//String
**boolean** z = s.contains( cs ) ; // 【 boolean contains( CharSequence ) 】<br /> **System**.out.println( z );
// 整个字符串中的每个字符的索引 一律 从 "左" 开始统计 ( 与数组相同 )<br /> **int** index = s.indexOf( '天' ) ; // 获取 '天' 在变量 s 所指向的字符串中首次出现的位置( 索引 )<br /> **System**.out.println( index );
index = s.indexOf( "好风光" ) ; // 获取 "好风光" 在变量 s 所指向的字符串中首次出现的位置( 索引 )<br /> **System**.out.println( index );
**System**.out.println( s.indexOf( '雨' ) ); // 若不存在即返回 -1
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**int** last = s.lastIndexOf( '天' ); // 获取 '天' 在变量 s 所指向的字符串中最后一次出现的位置( 索引 )<br /> **System**.out.println( last );
last = s.lastIndexOf( "好风光" ); // 获取 "好风光" 在变量 s 所指向的字符串中最后一次出现的位置( 索引 )<br /> **System**.out.println( last );
**System**.out.println( s.indexOf( "下雨" ) ); // 若不存在即返回 -1
}<br />}
/
1、 int indexOf( int ch , int from )
从 当前字符串中 指定位置(from) 开始寻找 指定字符 ( ch ) 首次出现的位置,若存在即返回该索引,否则返回 -1
2、int indexOf( String s , int from )
从 当前字符串中 指定位置(from) 开始寻找 指定字符串 ( s ) 首次出现的位置,若存在即返回该索引,否则返回 -1
3、int lastIndexOf( int ch , int from )
从 当前字符串中 指定位置(from) 开始反向寻找 指定字符 ( ch ) 最后一次出现的位置,若存在即返回该索引,否则返回 -1
即获取在 from 处及其之前 ch 最后一次出现的位置是什么
( 反向寻找的顺序是 from 、from - 1 、from - 2 、…….. )
4、int lastIndexOf( String s , int from )
从 当前字符串中 指定位置(from) 开始反向寻找 指定字符串 ( s ) 最后一次出现的位置,若存在即返回该索引,否则返回 -1
即获取在 from 处及其之前 s 最后一次出现的位置是什么
1、String concat( String ) 将当前 字符串 与 参数给定的字符串 拼接到一个新的字符串中并返回新字符串实例
* 2、String toUpperCase() 将当前 字符串 中所有的小写英文字符转换为大写后返回新的字符串实例
* 3、String toLowerCase() 将当前 字符串 中所有的大写英文字符转换为小写后返回新的字符串实例
* 4、boolean equals( Object ) String 类重写了 equals 方法用于比较 两个 String 实例中所包含的字符串是否相等
* 5、boolean equalsIgnoreCase( String ) 比较两个 String 实例中所包含的字符串是否相等 ( 忽略英文字母大小写 )
* 6、boolean contentEquals( CharSequence ) 用于比较参数指定的 字符序列 是否与 当前 String 实例所包含的 字符串内容 相等
* 7、int compareTo( String ) 用于比较两个字符串的 “大小” ( 当两个字符串相等时返回 零 ( 英文字母区分大小写 ) )
* 8、int compareToIgnoreCase( String ) 用于比较两个字符串的 “大小” ( 当两个字符串相等时返回 零 ( 英文字母不区分大小写 ) )
1、int length()
2、boolean isEmpty()
用于判断 当前 String 实例 所包含 字符串 是否为 空 ( 即 value.length 为 零 )
3、boolean isBlank() 【 JDK 11 新增的方法 】
用于 当前 String 实例 所包含 字符串 是否为 空白 ( 仅包含了 空格 、制表符 等字符 )
4、String trim() 剔除 当前 String 实例 所包含 字符串 中的首尾空白后返回新的 String 实例
1、boolean startsWith( String ) 判断 当前 String 实例 中所包含的字符串 是否以指定的 字符串 为【前缀】
2、boolean endsWith( String ) 判断 当前 String 实例 中所包含的字符串 是否以指定的 字符串 为【后缀】
3、boolean startsWith( String s , int from )
判断 当前 字符串 从指定位置开始 是否以指定的 字符串 为前缀
4、void getChars( int begin , int end , char[] array , int start )
将 当前 String 实例 中所包含的字符串 中 [ begin , end ) 之间的字符 拷贝到 array 数组的 start 位置
5、String substring( int begin ) 从当前字符串中的 begin 位置处开到字符串末尾截取并返回新字符串
6、String substring( int begin , int end ) 从当前字符串中截取[ begin , end ) 之间的内容并返回新字符串
* 7、CharSequence subSequence( int begin , int end ) 从当前字符串中截取[ begin , end ) 之间的内容并返回 CharSequence 实例
public class StringTestE {
public static void main(String**[] args) {
**final** **String** path = "D:/java-beginner/char-sequence/StringHelper.java" ;
**System**.out.println( path.startsWith( "D:" ) ); // true<br /> **System**.out.println( path.startsWith( "C:" ) ); // false
**System**.out.println( path.endsWith( ".java" ) ); // true<br /> **System**.out.println( path.endsWith( ".class" ) ); // false
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 判断 从索引 17 处开始 是否是 已 "char" 为前缀<br /> **System**.out.println( path.startsWith( "char" , 17 ) ); // true
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**char**[] array = **new** **char**[ 10 ];<br /> **System**.out.println( **Arrays**.toString( array ) );<br /> **String** str = "沧海一声笑滔滔两岸潮" ;
// 将 str 所指向的 String 实例中所包含的 字符串 中 [ 5 , 10 ) 之间的字符 拷贝到 array 数组中<br /> // 并在 array 数组的 索引 0 处 开始存放拷贝的字符<br /> str.getChars( 5 , 10, array , 0 );<br /> **System**.out.println( **Arrays**.toString( array ) );
str.getChars( 0 , 5, array , 5 );<br /> **System**.out.println( **Arrays**.toString( array ) );
**String** u = str.substring( 5 ); // [ 5 , length() - 1 ]<br /> **System**.out.println( u );
**String** v = str.substring( 3 , 7 ) ; // [ 3 , 7 )<br /> **System**.out.println( v );
**CharSequence** cs = str.subSequence( 2 , 8 ) ; // [ 2 , 8 )<br /> **System**.out.println( cs );<br /> **System**.out.println( cs.getClass() );
}<br />}
getChars/toCharArray/使用+运算符连接字符串
import java.util.Arrays;
/
1、测试 getChars( int , int , char[] , int ) 和 toCharArray()
2、理解使用 + 运算符 直接 连接 两个 字符串 字面量 所执行的操作
3、理解使用 + 运算符 连接 一个 字符串 字面量 和 另一个 String 类型的引用变量 所执行的操作
向 面试官 回答时,主要将 Java 8 中的实现过程
4、在 Java 11 中所完成的操作暂时仅做了解
/
public class StringTestF {
public static void main(String**[] args) {
**char**[] chars = **new** **char**[ 10 ];<br /> **final** **String** s = "黄沙百战穿金甲,不破楼兰终不还" ;<br /> s.getChars( 8 , 15, chars , 0 );<br /> **System**.out.println( **Arrays**.toString( chars ) );
**char**[] array = s.toCharArray();<br /> **System**.out.println( **Arrays**.toString( array ) );
**System**.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
**String** a = "黄沙百战" ; // 1 character strings ( String constant pool )<br /> **String** b = "穿金甲" ; // 1 character strings ( String constant pool )<br /> **String** c = "黄沙百战穿金甲" ; // 1 character strings ( String constant pool )<br /> // 当使用 + 连接 两个 字符串 直接量时,在 String 常量池中完成 字符串 的 连接操作,<br /> // 如果 新字符串 在 String常量池 中不存在,则首先将 新字符串 添加到 String 常量池 中并返回该串的地址<br /> // 如果 新字符串 在 String常量池 中已经存在 则直接返回已经存在的 字符串 的地址 ( 不再添加新拼接的字符串 )<br /> **String** d = "黄沙百战" + "穿金甲" ; // 至少在 JDK 11 中已经是在编译阶段就将两个字符串合并了<br /> **System**.out.println( c == d ); // true : 使用 == 比较两个变量时是在比较两个变量中存储的值<br /> **System**.out.println( **System**.identityHashCode( c ) );<br /> **System**.out.println( **System**.identityHashCode( d ) );
// 以下 三步 是 Java 8 中的做法<br /> // 1、StringBuilder sb = new StringBuilder( a ) ; // 创建一个字符缓冲区,并在其中存放 '黄' , '沙' , '百' , '战'<br /> // 2、sb.append( "穿金甲" ) ; // 在 字符缓冲区 中 追加 '穿' , '金' , '甲' ,此时在 字符缓冲区中存在 7 个字符<br /> // 3、sb.toString() ; // 在 toString 方法内部创建并返回一个新的 String 实例,其中封装了 "黄沙百战穿金甲"<br /> **String** e = a + "穿金甲" ; // 至少在 JDK 11 中已经是通过 invokedynamic 实现的<br /> **System**.out.println( c == e ); // false : 使用 == 比较两个变量时是在比较两个变量中存储的值<br /> **String** f = "黄沙百战" + b ;<br /> **System**.out.println( c == f ); // false
// StringBuilder sb = new StringBuilder();<br /> // sb.append( a );<br /> // sb.append( b );<br /> // sb.toString();<br /> **String** g = a + b ;<br /> **System**.out.println( c == g ); // false
}<br />}
String类中常用实例方法:intern
public class StringTestG {
public static void main(String[] args) {
**String** a = "黄沙百战" ;<br /> **String** b = "穿金甲" ;<br /> **String** c = "黄沙百战穿金甲" ;<br /> **String** d = a + b ;<br /> **System**.out.println( c == d ); // false
**System**.out.println( "~ ~ ~ ~ ~ ~ ~" );
// 当通过 某个String实例 来调用其 intern 方法时,<br /> // 如果 String常量池 中已经包含一个 与该String实例 所包含内容相等 ( 用 equals(Object)确定 ) 的 String实例,<br /> // 就直接返回在 String常量池 中已经存在的 String实例 ( 不再将当前的 String实例 添加到 String常量池 ) 。<br /> // 否则,将 此 String实例 添加到 String常量池 中,并返回 此String实例 的引用 ( 即返回 String常量池 中新增的 String实例 的地址 )<br /> **String** f = d.intern();<br /> **System**.out.println( c == f ); // true
**System**.out.println( "~ ~ ~ ~ ~ ~ ~" );
**String** s = **new** **String**( "不破楼兰终不还" );<br /> **String** x = **new** **String**( "不破楼兰终不还" );
**System**.out.println( s == x ); // false<br /> **System**.out.println( s.equals( x ) ); // true
**String** t = s.intern() ;<br /> **String** r = x.intern() ;<br /> **System**.out.println( t == r ); // true
}<br />}
使用CharacterStrings实现CharSequence
CharSequence是接口
public final class CharacterStrings extends Object implements CharSequence {
**private** **final** **char**[] value ;<br /> **private** **final** **int** size ;
**public** **CharacterStrings**( **String** s ) {<br /> **if**( s == **null** ) {<br /> **this**.value = **null** ;<br /> **this**.size = -1 ;<br /> } **else** {<br /> **this**.size = s.length() ;<br /> **this**.value = **new** **char**[ **this**.size ];<br /> s.getChars( 0 , size , value , 0 );<br /> }<br /> }<br /> @Override<br /> **public** **int** **length**() {<br /> **return** size ;<br /> }<br /> @Override<br /> **public** **char** **charAt**(**int** index) {<br /> **if**( index >= 0 && index <= size ) {<br /> **return** value[ index ] ;<br /> }<br /> **return** 0 ;<br /> }<br /> @Override<br /> **public** **CharSequence** **subSequence**(**int** start, **int** end) {<br /> **if**( start >= 0 && end <= size && start < end ) {<br /> **String** s = **new** **String**( value , start , end );<br /> **CharacterStrings** cs = **new** **CharacterStrings**( s );//调用本类构造<br /> **return** cs ;<br /> }<br /> **return** **null**;<br /> }
@Override<br /> **public** **String** **toString**() {<br /> **return** **new** **String**( **this**.value );<br /> }
**public** **static** **void** **main**(**String**[] args) {
**CharacterStrings** s = **new** **CharacterStrings**( "hello,world" );<br /> **System**.out.println( s.length() );<br /> **System**.out.println( s );
**CharSequence** c = s.subSequence( 0 , 6 );<br /> **System**.out.println( c.length() );<br /> **System**.out.println( c );
}
}
理解StringBuffer实例的可变性、测试常用的方法:append / insert / replace
1、字符串 ( character strings ) 缓冲区 ( buffer ) : string buffer 根据 Java 中类的命名规范命名为 StringBuffer
2、与 String 类的实例一样,StringBuffer 类的实例 也用于 封装 字符串 ( character strings )
3、与 String 类的实例 不可变 不同,StringBuffer 类的实例 是 可变的,因此每次操作 都会影响 StringBuffer 实例
4、StringBuffer 类中定义了大量的用来操作 字符串缓冲区 的方法: append / insert / replace / deleteCharAt / delete
StringBuffer buffer = new StringBuffer();
*System.out.println( “length : “ + buffer.length() + “ , capacity : “ + buffer.capacity() + “ , toString : “ + buffer );buffer.append( **false** );** ****// 在 字符缓冲区中 追加内容"false"**<br /> buffer.insert( 0 , "hello," );//在下标为0的位置插入"hello",即为hello,false<br />buffer.replace( 5 , 6 , "," );//用,替换下表5-6的字符<br /> int index = buffer.indexOf( "," );<br /> buffer.deleteCharAt( index );//找到,对应的下标并删除<br />buffer.delete( 5 , 10 );//删除下标【5,10)的字符
了解StringBuffer内部的一些方法是返回当前的StringBuffer对象
StringBuffer buffer = new StringBuffer( “hello” );
buffer.append( true ).append( 100 ).append( ‘A’ ).append( “你好” ).append( 3.14 );//所以可以一直添加
System.out.println( “length : “ + buffer.length() + “ , capacity : “ + buffer.capacity() + “ , toString : “ + buffer );
buffer.reverse(); // 翻转
通过StringBuilder实例测试setLength和trimToSize
1、StringBuilder 类的设计 与 StringBuffer 基本一致 ( 父类 、实现接口 、构造 、方法 )
2、StringBuilder 类中的 方法都没有 synchronized 修饰的,
而 StringBuffer 中所有 public 方法都是有 synchronized 修饰的
3、不论是 StringBuilder 还是 StringBuffer ,都可以使用 setLength 方法有效字符数 、通过 trimToSize 来调整容量。
public class StringBuilderTest {
public static void main(String[] args) {
**StringBuilder** builder = **new** **StringBuilder**( "hello" );<br /> **System**.out.println( "length : " + builder.length() + " , capacity : " + builder.capacity() + " , toString : " + builder );//length : 5 , capacity : 21 , toString : hello
builder.setLength( 0 ); // 设置 length 为 零 ( 有效字符数 为 零 )
**System**.out.println( "length : " + builder.length() + " , capacity : " + builder.capacity() + " , toString : " + builder );//length : 0 , capacity : 21 , toString :
builder.append( **true** );
**System**.out.println( "length : " + builder.length() + " , capacity : " + builder.capacity() + " , toString : " + builder );//length : 4 , capacity : 21 , toString : true
builder.trimToSize();//改变容量
**System**.out.println( "length : " + builder.length() + " , capacity : " + builder.capacity() + " , toString : " + builder );//length : 4 , capacity : 4 , toString : true
}<br />}