引言
字符串在任何语言里的日常使用频率都极高,深入地了解字符串很有意义。
从表面上看,Java中的字符串就是双引号之间的一系列字符形成的串;
能够想到字符串都是 java.langf.String
类的实例,即字符串都是对象(本质是打包字符数组的对象);
1. 字符串对象
1.1 字符串的定义
既然是对象,必然地 new 以下才像话:
String str = new String("hello world!");
由于字符串的使用频率高和效能考虑,我们可以使用更为常见对的简洁写法:String str = "hello world";
就像数组定义的简洁写法一样。
1.2 常用的字符串操作
1)length()方法
length() 返回字符串的长度。
无论是字母、数字,还是汉字,每个字符的长度都是1。
2)charAt()和indexOf() 方法
前者返回字符串中指定索引处的字符。
后者返回指定字符/子串在此字符串中第一次出现处的索引。
字符串中第一个字符的索引值是0,第二个字符的索引值是1,依次类推。
3)contains() 方法
用来检测字符串是否包含某个子串,返回布尔值。
4)replace() 方法
字符串替换,用来替换字符串中所有指定的子串,例如:
String str1 = "The url of weixueyuan is www.weixueyuan.net!";
String str2 = str1.replace("weixueyuan", "微学苑");
System.out.println(str1);
System.out.println(str2);
/*
输出结果:
The url of weixueyuan is www.weixueyuan.net!
The url of 微学苑 is www.微学苑.net!
*/
注意:replace() 方法不会改变原来的字符串,而是生成一个新的字符串。
5)split() 方法
以指定字符串作为分隔符,对当前字符串进行分割,分割的结果是一个字符串数组。
6)toCharArray()
将此字符串转换为一个新的字符数组,以便当作数组使用。
7)….
更多方法参考JDK API文档
1.3 字符串转基本类型使用
如果是整数、浮点数等基本数据类型形式的字符串,可以利用对应的打包类的转化方法,直接转成基本类型使用:
byte b = Byte.parseByte(str);
short s = Short.parseShort(str);
/*
*int long float double
*/
boolean boo = Boolean.parseBoolean(str);
2. 字符串特性
每种语言里的字符串的特性不尽相同,例如 JavaScript
里单引号和双引号通用。
Java里的字符串有几点必须注意的特性。
2.1 字符串常量与字符串池
String name1 = "xiaoWU";
String name2 = "xiaoWu";
String name3 = new String("xiaoWu");
System.out.println(name1==name3); //理所当然,false
System.out.println(name1==name2); //true ?! 参考至同一对象!
按照正常的对象参考考虑,这里应该是 false,但是对应字符串对象,就要注意了。
Java中,用 “” 写下的字符串称为 字符串常量(String literal) ,基于节省内存考虑,以 “” 包围的字符串常量,只要内容相同(序列、大小写相同),无论它在代码中出现几次, JVM 只为它建立一个String实例,并放在 字符串池(String pool) 中维护。
上面的name1 和 name2 实际上是参考至同一个字符串常量,所以返回了 true;
但是 new 一定是建立新对象(堆)(尽管对象内容是一样的),所以 name3 和 name1不是参考至同一对象。
2.2 不可变动(immutable)字符串
String字符串与数组有一个共同点,就是它们被初始化后,长度是不变的,并且内容也不变。如果要改变它的值,就会产生一个新的字符串。但是我们经常使用 + 连接字符串:
String str1 = "heng";
String str2 = name1 + “~ ha~";
System.out.println(str2); //"heng~ ha~"
这又是怎么回事呢?
事实上,反编译这段代码,可以看见:
String s = "heng";
String s1 = (new StringBuilder()).append(s).append("~ ha~").toString();
System.out.println(s1);
所以,使用 + 连接字符串,会变成建立 java.lang.StringBuilder 对象,即频繁地使用 + 连接字符串时,会频繁地建立新对象。so 不要将 + 用在重复性的连接场合。
3. StringBuffer与StringBuider
String 的值是不可变的,每次对String的操作都会生成新的String对象,不仅效率低,而且耗费大量内存空间。
StringBuffer类和String类一样,也用来表示字符串,但是StringBuffer的内部实现方式和String不同,在进行字符串处理时,不生成新的对象,在内存使用上要优于String。
StringBuffer 默认分配16字节长度的缓冲区,当字符串超过该大小时,会自动增加缓冲区长度,而不是生成新的对象。
StringBuilder是 JDK5 知乎新增的类,它和StringBuffer具有相同的操作接口,两个类功能基本相似,方法也差不多,主要区别在于StringBuffer类的方法是多线程安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。
使用情况:
操作少量的数据使用 String;
单线程操作大量数据使用 StringBuilder;
多线程操作大量数据使用 StringBuffer。