首页 > 技术文章 > String、StringBuilder、StringBuffer

cing 2017-10-30 19:21 原文

 

一、String

1.基本方法

 1 1)length():String中字符的个数。
 2 
 3 2)charAt(int index):取得String中该索引位置上的char。
 4 
 5 3)toCharArray():生成一个char[],包含String的所有字符。
 6 
 7 4)equals():比较两个String的内容是否相同。
 8 
 9 5)compareTo(String anotherString):按词典顺序比较String的内容,比较结果为负数、零或正数。
10 
11 6)contains(CharSequence s):如果该String对象包含参数的内容,则返回true。
12 
13 7)equalsIgnoreCase():忽略大小写,如果两个String的内容相同,则返回true。
14 
15 8)startsWith():返回boolean结果,以表明该String是否以此参数起始。
16 
17 9)endsWith(String s):返回boolean结果,以表明此参数是否是该字符串的后缀。
18 
19 10)isEmpty():当且仅当length()为0时返回true。
20 
21 11)split(String regex):根据给定正则表达式的匹配拆分此字符串。
22 
23   或|,点.,加+,乘*,在字符串中出现时,如果这个字符串需要被split,则split时候,需要在前面加两个反斜杠。
24 
25       与&,在split时候,不需要转义。
26 
27 12)substring(int beginIndex, int endIndex):返回一个新字符串,它是此字符串的一个子字符串。
28 
29 13)toLowerCase():转为小写。
30 
31 14)toUpperCase():转为大写。
32 
33 15)trim():返回字符串的副本,忽略前导空白和尾部空白。
34 
35 16)valueOf(char[] data):返回char数组参数的字符串表示形式。
View Code

2.不可变性

java中的不可变类:

1. 可变类和不可变类(Mutable and Immutable Objects)的初步定义: 
可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容。 
不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。不可变类的实例一但创建,其内在成员变量的值就不能被修改。 
举个例子:String和StringBuilder,String是immutable的,每次对于String对象的修改都将产生一个新的String对象,而原来的对象保持不变,而StringBuilder是mutable,因为每次对于它的对象的修改都作用于该对象本身,并没有产生新的对象。

String对象是不可变的。也就是说可以给一个String对象加任意多的别名。因为String对象具有只读特性,所以指向它的任何引用都不可能改变它的值。

 1 public class Immutable {
 2     public static String upcase(String s) {
 3         return s.toUpperCase();
 4     }
 5     public static void main(String[] args) {
 6         String q = "howdy";
 7         print(q);
 8         String qq = upcase(q);
 9         print(qq);
10         print(q);
11     }
12 }
13 //结果:howdy HOWDY howdy
View Code

上述代码的解释:当把q传给upcase()方法时,实际传递的是引用的一个拷贝,这个引用所指的对象一直待在某个物理位置上。而对于upcase()的定义,传入其中的引用有了名字s,只有upcase()运行的时候,局部引用s才存在,一旦upcase()运行结束,s就消失了。而upcase()的返回值,其实只是最终结果的引用。而原本的q还在原地。

因为String的不可变性,所对string字符串做的所有的变更字符串的操作,都会导致new的产生,这样也就改变了upcase传进去的string的地址,所以原q是没有任何变化的。

通过反射改变String对象:

 1     //创建字符串"Hello World", 并赋给引用s
 2     String s = "Hello World"; 
 3     System.out.println("s = " + s); //Hello World
 4 
 5     //获取String类中的value字段
 6     Field valueFieldOfString = String.class.getDeclaredField("value");
 7     //改变value属性的访问权限
 8     valueFieldOfString.setAccessible(true);
 9 
10     //获取s对象上的value属性的值
11     char[] value = (char[]) valueFieldOfString.get(s);
12     //改变value所引用的数组中的第5个字符
13     value[5] = '_';
14     System.out.println("s = " + s);  //Hello_World
View Code

3.重载的“+”操作符

不可变行带来一定的效率问题。而Java仅对"+"和"+="两个操作符重载过,且Java不允许程序员重载任何操作符。

1 public class Main {
2     public static void main(String[] args) {
3         String mango = "mango";
4         String s = "abc" + mango + "def" + 47;
5         print(s);
6     }
7 }
8 //结果:abcmangodef47
View Code

在s = "abc" + mango + "def" + 47;的语法中,编译器自动创建了一个StringBuilder对象,用以构造最终的String,并为每个字符串调用一次StringBuilder的append()方法,总计4次。最后调用toString()生成结果,并存为s。

 1 public class Test {
 2     public String implicit(String[] fields) {
 3         String result = "";
 4         for(int i = 0; i < fields.length; i++) {
 5             result += fields[i];
 6         }
 7         return result;
 8     }
 9     public String explicit(String[] fields) {
10         StringBuilder result = new StringBuilder();
11         for(int i = 0; i < fields.length; i++) {
12             result.append(fields[i]);
13         }
14         return result.toString();
15     }
16 }
View Code

implicit()方法:每循环一次,会创建一个新的StringBuilder对象,而每循环一次,之前创建的StringBuilder对象就会被gc回收。

explicit()方法:只生成一个StringBuilder对象。

4.new String("abc")创建几个对象

如果常量池中原来有“abc”,则只创建一个对象;否则创建两个对象。

总结:需要经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统新能产生影响,特别当内存中无引用对象多了以后,GC就会开始工作,会拖慢速度。

适用于:少量的字符串操作的情况。

二、StringBuilder:是非线程安全的

 适用于:单线程下在对字符串进行大量操作的情况

三、StringBuffer:是线程安全的

适用于:多线程下对字符串进行大量操作的情况。

 

三者运行效率的一般情况:StringBuilder>StringBuffer>String

特殊情况:

String str="abc"+"de";//更快
StringBuilder stringBuilder=new StringBuilder().append("abc").append("de");

这里的str会比stringBuilder快,因为str的赋值操作相当于str = "abcde",之所以会这样是因为有字符串常量池的存在。

而如果写成下面的形式,string依旧很慢:

String str1="abc";
String str=str1+"de";

因为会导致新对象的产生。

 

从存取上来说,String>StringBuffer

从多次改编上来说,StringBuffer>String

推荐阅读