一、String类介绍 点击此处返回总目录 二、String类的构造方法
三、String类的常用方法 四、String类练习 五、StringBuffer类 六、StringBuffer类的构造方法 七、StringBuffer类的常用方法 八、StringBuffer类练习 九、StringBuilder类 一、String类介绍 Java当中所有的字符串(用双引号引起来的)都是String类的对象。在Java中,一切都是对象,类是用来描述的对象的。字符串也是对象,String类就是描述字符串对象的。 注意:1 字符串对象的声明: String str = "liupc"; //String类不用写new,因为这样简单。也可以写成String str = new String("liupc");。 //其中:String是类;str是引用类型变量;"liupc"是类的对象。 String str = new String("liupc"); //使用这种方式时,会在堆上创建两个对象。【例2】 2 字符串是常量,他们的值在创建之后不能再更改。字符串的本质是一个字符数组。【例1】 例1:字符串是常量
package cn.itcast.demo01; public class Stringdemo { public static void main(String[] args) { String str = "liupc"; str = "aaa"; System.out.println(str); //aaa。str是引用类型变量,他是可以再指向另一个字符串的。字符串是常量是指"liupc"不能改变。 字符串本身是一个对象。"liupc"是一个对象,他是不能改变的。变量的指向变了。 } } |
为什么字符串是常量?我们看一下String类的实现:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; //可以看到字符串的本质是一个一维数组,而且是final的。一旦建立,就不变了。 /** Cache the hash code for the string */ private int hash; // Default to 0 ...... } |
例1的内存解释: 步骤一:main()方法入栈。 步骤二:堆里面有个小的区域叫常量池。里面存放了a,b,c....,z,A,B,C,..Z。当执行String str = "liupc"时,首先在堆上从常量池中拿出字符 来用,创建一个字符数组,为{'l','i','u','p','c'}。 步骤三:栈上创建str,指向刚才的字符数组。 步骤四:当指向str="aaa";时,重新创建一个字符数组{'a','a','a'}(不是把{'l','i','u','p','c'}改成{'a','a','a'},而是重新创建)。 步骤五:str指向这个数组。 例2:String str = new String("liupc"); 与String str = "liupc";的不同。
package cn.itcast.demo02; public class Stringdemo { public static void main(String[] args) { String str1 = "aaa"; String str2 = new String("bbb"); System.out.println(str1 == str2); //false。不同的对象。解释见下面的内存分析。 System.out.println(str1.equals(str1)); //true。比较的是字符串本身。 String str3 = "ccc"; String str4 = "ccc"; System.out.println(str3 == str4); //true。同一个对象。 System.out.println(str3.equals(str4)); //true。比较的是字符串本身。 String str5 = new String("ddd"); String str6 = new String("ddd"); System.out.println(str5 == str6); //false。不同的对象。解释见下面的内存分析。 System.out.println(str5.equals(str6)); //true。比较的是字符串本身。 } } |
例2的内存分析: 如上图,左边的例子,当执行String str1 = new String("abc")时,实际上在内存中创建了两个对象。首先"abc"是一个对象,其次new String()又是一个对象。new String()对象中存放的是"abc"对象的地址。然后str1指向new String()对象。 当执行 String str2 = "abc"时,运行时期,虚拟机做了优化,发现内存中有"abc",因此str2指向直接了之前的对象"abc"。 当执行System.out.println(str1 == str2);时,比较的是两个对象的地址,不同,为false。 当执行System.out.println(str1.equals(str2));时,因为String()类对Object类的equals()方法做了重写,所以比较的是字符串。相同为true。 二、String类的构造方法【详见API文档】 1. public String(byte[] bytes) //通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String 。 //传递的是字节数组。注意范围。 //平台指:操作系统。默认字符集指操作系统中的默认编码表。在我们安装的中文版系统里面,默认编 码表是GBK,但是一切编码表都兼容ASCII编码表。 //将字节数组的每个字节查询编码表得到的结果,来构造字符串。【例1】 //当为正数是查询的是ASC码表,当为负数时查询的是GBK表。【例2】 2. public String(byte[] bytes, int offset, int length) //offset表示从第几个开始,length表示有几个字节转成字符串。【例3】 3. public String(char[] value) //将字符数组转成字符串。【例4】 4. public String(char[] value, int offset, int count) //将字符数组的一部分转化成字符串。【例5】 例1:
package cn.itcast.demo01; public class Test { public static void main(String[] args) { byte[] by = {65,66,67,68}; //byte数组。字节数是正的,查询ASCII码表。如果是负的,查询GBK表。 String s = new String(by); //调用构造方法。 System.out.println(s); //ABCD。将字节数组的每个字节查询编码表得到的结果,来构造字符串。 } } |
例2:当字节数组中字节为正数时,查询的是ASCII码表;为负时,查询GBK表。
package cn.itcast.demo03; public class Test { public static void main(String[] args) { byte[] by = {-65,-66,-67,-68}; //字节为负,查询的是GBK编码表。要注意两个字节表示一个汉字,所以要写就写偶数个。 String s = new String(by); System.out.println(s); //烤郊。 } } |
例3:将字符数组的一部分转成字符串。
package cn.itcast.demo03; public class Test { public static void main(String[] args) { byte[] by = {65,66,67,68}; String s = new String(by,1,2); //从66开始的两个字节转成字符串。所以66,67转成字符串。 System.out.println(s); //BC } } |
例4:将字符数组转化成字符串。
package cn.itcast.demo03; public class Test { public static void main(String[] args) { char[] by = {65,66,67,'吃','D'}; String s = new String(by); System.out.println(s); //ABC吃D。 } } |
例5:将字符数组的一部分转化成字符串。
package cn.itcast.demo03; public class Test { public static void main(String[] args) { char[] by = {65,66,67,'吃','D'}; String s = new String(by,1,3); System.out.println(s); //BC吃 } } |
三、String类常用方法【详见API文档】 1. toString() //String类对toString()方法进行了重写,不在是得到对象地址,而是得到字符串的值。【例1】 2. equals() //String类对equals()方法进行了重写,不再是比较对象地址,而是比较字符串。【一、例2】 3. public boolean equalsIgnoreCase(String anotherString) //比较两个字符串,忽略大小写【例11】 4. public int length() //返回字符串的长度。"liupc"的长度为3。【例2】 5. public String substring(int beginIndex) //获取从beginIndex开始的到字符串结尾的字符串。【例3】 6. public String substring(int beginIndex, int endIndex) //截取字符串。含第头,不含尾。【例4】 7. public boolean startsWith(String prefix) //判断是否以某个字符串为前缀。【例5】 8. public boolean endsWith(String suffix) //判断是否以某个字符串为后缀。【例6】 9. public boolean contains(CharSequence s) //判断一个字符串是否包含另一个字符串。【例7】 10. public int indexOf(String str) //查找一个字符或字符串第一次出现的位置,不存在返回-1。【例8】 11. public byte[] getBytes() //将字符串转化为字节数组。【例9】 12. public char[] toCharArray() //将字符串转化为字节数组。【例10】 13. public char charAt(int index) //返回指定索引处的 char 值。【例12】 14. public String toLowerCase() //所有字母都转成小写【例13】 15. public String toUpperCase() //所有字母都转成大写【例13】 例1:String类重写了toString()方法。
package cn.itcast.demo01; public class Test{ public static void main(String[] args) { String str = "liupc"; System.out.println(str); //liupc。toString()方法是Object类的。按照Object类的toString()方法里讲的,当System.out.println()方 法的参数是一个对象时,会自动调用toString()方法。所以这句话相当于System.out.println(str.toString()); 而toString()方法得到的是对象的地址。这里按道理应该输出对象"liupc"的地址,但是输出的是:liupc。只 有一种情况就是,String类对toString()方法进行了重写。 } } |
例2:length()的使用
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "liu"; System.out.println(s.length()); //3. } } |
例3:字符串截取
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "liu"; System.out.println(s.substring(0)); //"liu" System.out.println(s.substring(1)); //"iu" System.out.println(s.substring(3)); //"",即空字符串。 //System.out.println(s.substring(4)); //java.lang.StringIndexOutOfBoundsException } } |
例4:字符串截取。
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "liupc"; System.out.println(s.substring(1,3)); //"iu"。包含头,不包含尾。 } } |
例5:判断是否以一个字符串开始
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "liupc"; System.out.println(s.startsWith("li")); //true System.out.println(s.startsWith("i")); //false } } |
例6:判断字符串的后缀是不是另一个字符串
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "liupc"; System.out.println(s.endsWith("pc")); //true System.out.println(s.startsWith("i")); //false } } |
例7:判断是否包含另一个字符串
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "liupc"; System.out.println(s.contains("up")); //true System.out.println(s.contains("ip")); //false } } |
例8:查找一个字符或字符串第一次出现的位置。
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "liui"; System.out.println(s.indexOf("iu")); //1 System.out.println(s.indexOf('i')); //1。第一个出现的位置。 System.out.println(s.indexOf("pc")); //-1。找不到显示-1。 } } |
例9:将字符串转化为字节数组
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "烤郊"; byte[] by =s.getBytes(); for(int i = 0;i<by.length;i++){ if(i == by.length -1){ System.out.println(by[i]); }else{ System.out.print(by[i]+","); //-65,-66,-67,-68 } } } } |
例10:将字符串转化为字符数组。
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String s = "烤郊"; char[] by =s.toCharArray(); for(int i = 0;i<by.length;i++){ if(i == by.length -1){ System.out.println(by[i]); }else{ System.out.print(by[i]+","); //烤,郊 } } } } |
例11:比较两个字符串是否相等,忽略大小写
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String str1 = "Abcd"; String str2 = "aBcD"; System.out.println(str1.equalsIgnoreCase(str2)); //true } } |
例12:返回指定索引处的 char 值
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String str1 = "Abcd"; System.out.println(str1.charAt(2)); //c } } |
例13:转化成大写或小写
package cn.itcast.demo03; public class Test { public static void main(String[] args) { String str1 = "AbcD"; System.out.println(str1.toLowerCase()); //abcd System.out.println(str1.toUpperCase()); //ABCD } } |
四、String类练习 练习1:获取指定字符串中,大写字母、小写字母、数字的个数。
package cn.itcast.demo04; public class Count { public static void main(String[] args) { String str = "abc12ABCD"; int count1 = 0; int count2 = 0; int count3 = 0; char ch = ' '; for(int i = 0;i<str.length();i++){ ch = str.charAt(i); if(ch <= '9' && ch>= '0'){ count1++; }else if(ch<='z' && ch>='a'){ count2++; }else if(ch<='Z' && ch>='A'){ count3++; } } System.out.println("数字个数:"+count1); //数字个数:2 System.out.println("小写字母个数:"+count2); //小写字母个数:3 System.out.println("大写字母个数:"+count3); //大写字母个数:4 } } |
练习2:将字符串中,第一个字母转换成大写,其他字母转换成小写,并打印改变后的字符串。(假设全是字母)
package cn.itcast.demo05; public class Convert { public static void main(String[] args) { System.out.println(convert("bbCdd")); //Bbcdd System.out.println(convert("CddEe")); //Cddee } public static String convert(String str){ return (str.substring(0, 1).toUpperCase()+str.substring(1).toLowerCase()); } } |
练习3:查询大字符串中,出现指定小字符串的次数。如“hellojava,nihaojava,javazhenbang”中查询出现“java”的次数。
package cn.itcast.demo06; public class Conut { public static void main(String[] args) { System.out.println(count("liupcaa,liupcbb,liupccc","liupc")); //3 System.out.println(count("aaaaaa","aa")); //3 StringBuffer b ; } public static int count(String str1, String str2){ int count = 0; int index; while((index = str1.indexOf(str2))!=-1){ count ++; str1 = str1.substring(index+str2.length()); } return count; } } |
五、StringBuffer类 String类虽然功能很强大,但是有一个弱点,就是String类是不可变的,一旦定义好之后就不可变了,这样会造成内存浪费问题。所以,JDK为了解决字符串的内存问题,开发了StringBuffer类,即字符串缓冲区类,他的出现目的就是为了提高字符串的操作效率。 查看StringBuffer的内部实现,为char[] value 。与String类一样,也是一个字符数组,但是他前面没有final修饰,所以是可以改变的。 六、StringBuffer类的构造函数 1. public StringBuffer() //构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。 2. public StringBuffer(String str) //构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。 七、StringBuffer类常用的函数 1. public StringBuffer append(Object obj) //将任意对象添加到字符串缓冲区中。【例1】 2. public StringBuffer delete(int start, int end) //删除指定范围内的数据。含头不含尾。[start,end)【例2】 3. public StringBuffer insert(int offset, Object obj) //在offset的位置上,插入任意对象的数据。注意不是在offset之后插入。【例3】 4. public StringBuffer replace(int start, int end, String str) //将[start,end)的字符替换成str。【例4】 5. public StringBuffer reverse() //将缓冲区的字符反转。【例5】 6. public String toString() //对toString()进行了重写。将可变的缓冲区对象转换为不可变的字符串对象。【例6】 例1:append追加
package cn.itcast.demo08; public class Test { public static void main(String[] args) { StringBuffer s = new StringBuffer(); s.append("aa").append(12).append(true); System.out.println(s); //aa12true } } |
例2:删除指定范围内的数据
package cn.itcast.demo08; public class Test { public static void main(String[] args) { StringBuffer s = new StringBuffer("liupc"); s.delete(1, 3); System.out.println(s); //lpc s.delete(0, s.length()); //如何删除所有的数据 System.out.println(s); //"" } } |
例3: 在索引的位置上插入数据
package cn.itcast.demo08; public class Test { public static void main(String[] args) { StringBuffer s = new StringBuffer("liu"); s.insert(1,"bc"); System.out.println(s); //lbciu } } |
例4:替换
package cn.itcast.demo08; public class Test { public static void main(String[] args) { StringBuffer s = new StringBuffer("liupc"); s.replace(1, 3, "aa"); System.out.println(s); //laapc } } |
例5:将缓冲区的字符反转。
package cn.itcast.demo08; public class Test { public static void main(String[] args) { StringBuffer s = new StringBuffer("liupc"); s.reverse(); System.out.println(s); //cpuil } } |
例6:将缓冲区的所有字符转换成字符串。
package cn.itcast.demo08; public class Test { public static void main(String[] args) { StringBuffer s = new StringBuffer("liupc"); String str = s.toString(); System.out.println(str); //liupc } } |
八、StringBuffer类练习 练习:将一个数组int[] arr= {12,13,14}转化成字符串"[12,13,14]"。
package cn.itcast.demo07; public class Test { public static void main(String[] args) { int a[] = {12,3,4,56,7}; StringBuilder s = new StringBuilder(); s.append("["); for(int i = 0 ;i<a.length;i++){ if(i == a.length-1){ s.append(a[i]).append("]"); }else{ s.append(a[i]).append(","); } } System.out.println(s); //[12,3,4,56,7] } } |
九、StringBuilder类 StringBulider类中的方法与StringBuffer中的方法完全一样。区别是,StringBuilder类是线程不安全的类,而StringBuffer类是线程安全的类。安全意味着运行速度慢。 此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。 |