Object Object类是类层次结构的根类。每个类都使用 Object 作为超类。每个类都直接或者间接的继承自Object类。
Object 中常用方法有:
1 2 3 4 5 6 7 8 9 10 11 public int hashCode () public final Class getClass () public String toString () protected Object clone () protected void finalize ()
equals() 方法 1. 等价关系
Ⅰ 自反性
Ⅱ 对称性
1 x.equals(y) == y.equals(x);
Ⅲ 传递性
1 2 if (x.equals(y) && y.equals(z)) x.equals(z);
Ⅳ 一致性
多次调用 equals() 方法结果不变
1 x.equals(y) == x.equals(y);
Ⅴ 与 null 的比较
对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false
2. 等价与相等
对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。
对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。
1 2 3 4 Integer x = new Integer (1 );Integer y = new Integer (1 );System.out.println(x.equals(y)); System.out.println(x == y);
3. 实现
检查是否为同一个对象的引用,如果是直接返回 true;
检查是否是同一个类型,如果不是,直接返回 false;
将 Object 对象进行转型;
判断每个关键域是否相等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class EqualExample { private int x; private int y; private int z; public EqualExample (int x, int y, int z) { this .x = x; this .y = y; this .z = z; } @Override public boolean equals (Object o) { if (this == o) return true ; if (o == null || getClass() != o.getClass()){ return false ; } EqualExample that = (EqualExample) o; if (x != that.x) return false ; if (y != that.y) return false ; return z == that.z; } }
hashCode() 方法 hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价 。
在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等 。
下面的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。 我们希望将这两个对象当成一样的,只在集合中添加一个对象,但是因为 EqualExample 没有实现 hasCode() 方法, 因此这两个对象的散列值是不同的,最终导致集合添加了两个等价的对象。
1 2 3 4 5 6 7 EqualExample e1 = new EqualExample (1 , 1 , 1 );EqualExample e2 = new EqualExample (1 , 1 , 1 );System.out.println(e1.equals(e2)); HashSet<EqualExample> set = new HashSet <>(); set.add(e1); set.add(e2); System.out.println(set.size());
理想的散列函数应当具有均匀性,即不相等的对象应当均匀分布到所有可能的散列值上。 这就要求了散列函数要把所有域的值都考虑进来 。 可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。 R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位。
一个数与 31 相乘可以转换成移位和减法:31*x == (x<<5)-x
,编译器会自动进行这个优化。
1 2 3 4 5 6 7 8 @Override public int hashCode () { int result = 17 ; result = 31 * result + x; result = 31 * result + y; result = 31 * result + z; return result; }
了解:IDEA中 Alt+Insert 快捷键就可以快速生成 hashCode() 和 equals() 方法。
toString() 方法 默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示。
1 2 3 4 5 6 7 8 public class ToStringExample { private int number; public ToStringExample (int number) { this .number = number; } }
1 2 ToStringExample example = new ToStringExample (123 );System.out.println(example.toString());
1 ToStringExample@4554617c
clone() 方法 1. Cloneable
clone() 是 Object 的 protected 方法 ,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。
1 2 3 4 public class CloneExample { private int a; private int b; }
1 2 3 CloneExample e1 = new CloneExample ();
重写 clone() 得到以下实现:
1 2 3 4 5 6 7 8 9 10 public class CloneExample { private int a; private int b; @Override public CloneExample clone () throws CloneNotSupportedException { return (CloneExample)super .clone(); } }
1 2 3 4 5 6 CloneExample e1 = new CloneExample ();try { CloneExample e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); }
1 java.lang.CloneNotSupportedException: CloneExample
以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接口。
应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法 。
Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException 。
1 2 3 4 5 6 7 8 9 public class CloneExample implements Cloneable { private int a; private int b; @Override public Object clone () throws CloneNotSupportedException { return super .clone(); } }
2. 浅拷贝
拷贝对象和原始对象的引用类型引用同一个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class ShallowCloneExample implements Cloneable { private int [] arr; public ShallowCloneExample () { arr = new int [10 ]; for (int i = 0 ; i < arr.length; i++) { arr[i] = i; } } public void set (int index, int value) { arr[index] = value; } public int get (int index) { return arr[index]; } @Override protected ShallowCloneExample clone () throws CloneNotSupportedException { return (ShallowCloneExample) super .clone(); } }
1 2 3 4 5 6 7 8 9 10 11 ShallowCloneExample e1 = new ShallowCloneExample ();ShallowCloneExample e2 = null ;try { e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } e1.set(2 , 222 ); System.out.println(e1.get(2 )); System.out.println(e2.get(2 ));
3. 深拷贝
拷贝对象和原始对象的引用类型引用不同对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class DeepCloneExample implements Cloneable { private int [] arr; public DeepCloneExample () { arr = new int [10 ]; for (int i = 0 ; i < arr.length; i++) { arr[i] = i; } } public void set (int index, int value) { arr[index] = value; } public int get (int index) { return arr[index]; } @Override protected DeepCloneExample clone () throws CloneNotSupportedException { DeepCloneExample result = (DeepCloneExample) super .clone(); result.arr = new int [arr.length]; for (int i = 0 ; i < arr.length; i++) { result.arr[i] = arr[i]; } return result; } }
1 2 3 4 5 6 7 8 9 10 DeepCloneExample e1 = new DeepCloneExample ();DeepCloneExample e2 = null ;try { e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } e1.set(2 , 222 ); System.out.println(e1.get(2 )); System.out.println(e2.get(2 ));
4. clone() 的替代方案
使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。 Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class CloneConstructorExample { private int [] arr; public CloneConstructorExample () { arr = new int [10 ]; for (int i = 0 ; i < arr.length; i++) { arr[i] = i; } } public CloneConstructorExample (CloneConstructorExample original) { arr = new int [original.arr.length]; for (int i = 0 ; i < original.arr.length; i++) { arr[i] = original.arr[i]; } } public void set (int index, int value) { arr[index] = value; } public int get (int index) { return arr[index]; } }
1 2 3 4 5 CloneConstructorExample e1 = new CloneConstructorExample ();CloneConstructorExample e2 = new CloneConstructorExample (e1);e1.set(2 , 222 ); System.out.println(e1.get(2 )); System.out.println(e2.get(2 ));
String String 被声明为 final,因此它不可被继承。
内部使用 char 数组存储数据,该数组被声明为 final , 这意味着 value 数组初始化之后就不能再引用其它数组。 并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变。
1 2 3 4 public final class String implements java .io.Serializable, Comparable<String>, CharSequence { private final char value[];
构造方法 1 2 3 4 5 6 7 8 9 10 11 public String () public String (byte [] bytes) public String (byte [] bytes,int index,int length) public String (char [] value) public String (char [] value,int index,int count) public String (String original)
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public class StringDemo { public static void main (String[] args) { String s=new String (); System.out.println("s:" +s); System.out.println("s.length=" +s.length()); System.out.println("-----------------------" ); byte [] bys={97 ,98 ,99 ,100 ,101 }; String s2=new String (bys); System.out.println("s2:" +s2); System.out.println("s2.length=" +s2.length()); System.out.println("-----------------------" ); String s3=new String (bys,0 ,3 ); System.out.println("s3:" +s3); System.out.println("s3.length=" +s3.length()); System.out.println("-----------------------" ); char [] chs={'a' ,'b' ,'c' ,'d' ,'e' }; String s4=new String (chs); System.out.println("s4:" +s4); System.out.println("s4.length=" +s4.length()); System.out.println("-----------------------" ); String s5=new String (chs,0 ,3 ); System.out.println("s5:" +s5); System.out.println("s5.length=" +s5.length()); System.out.println("-----------------------" ); String s6=new String ("abcde" ); System.out.println("s6:" +s6); System.out.println("s6.length=" +s6.length()); } }
字符串的特点:一旦被赋值,就不能改变
1 2 3 4 5 public static void test () { String s = "hello" ; s += "world" ; System.out.println("s:" + s); }
小练习:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static void test2 () { String s1 = new String ("hello" ); String s2 = new String ("hello" ); System.out.println(s1 == s2); System.out.println(s1.equals(s2)); String s3 = new String ("hello" ); String s4 = "hello" ; System.out.println(s3 == s4); System.out.println(s3.equals(s4)); String s5 = "hello" ; String s6 = "hello" ; System.out.println(s5 == s6); System.out.println(s5.equals(s6)); }
判断功能 1 2 3 4 5 6 7 8 9 10 11 boolean equals (Object obj) boolean equalsIgnoreCase (String str) boolean contains (String str) boolean startsWith (String str) boolean endsWith (String str) boolean isEmpty ()
注意:字符串内容为空和字符串对象为空。
1 2 String s = "" ;String s = null ;
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public class StringDemo3 { public static void main (String[] args) { String s1 = "helloworld" ; String s2 = "helloworld" ; String s3 = "HelloWorld" ; System.out.println("equals:" + s1.equals(s2)); System.out.println("equals:" + s1.equals(s3)); System.out.println("-----------------------" ); System.out.println("equals:" + s1.equalsIgnoreCase(s2)); System.out.println("equals:" + s1.equalsIgnoreCase(s3)); System.out.println("-----------------------" ); System.out.println("contains:" + s1.contains("hello" )); System.out.println("contains:" + s1.contains("hw" )); System.out.println("-----------------------" ); System.out.println("startsWith:" + s1.startsWith("h" )); System.out.println("startsWith:" + s1.startsWith("hello" )); System.out.println("startsWith:" + s1.startsWith("world" )); System.out.println("-----------------------" ); System.out.println("startsWith:" + s1.endsWith("d" )); System.out.println("startsWith:" + s1.endsWith("world" )); System.out.println("startsWith:" + s1.endsWith("hello" )); System.out.println("-----------------------" ); System.out.println("isEmpty:" + s1.isEmpty()); String s4 = "" ; String s5 = null ; System.out.println("isEmpty:" + s4.isEmpty()); } }
获取功能 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int length () char charAt (int index) int indexOf (int ch) int indexOf (String str) int indexOf (int ch,int fromIndex) int indexOf (String str,int fromIndex) String substring (int start) String substring (int start,int end)
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public class StringDemo4 { public static void main (String[] args) { String s = "helloworld" ; System.out.println("s.length:" + s.length()); System.out.println("----------------------" ); System.out.println("charAt:" + s.charAt(7 )); System.out.println("----------------------" ); System.out.println("indexOf:" + s.indexOf('l' )); System.out.println("----------------------" ); System.out.println("indexOf:" + s.indexOf("owo" )); System.out.println("----------------------" ); System.out.println("indexOf:" + s.indexOf('l' , 4 )); System.out.println("indexOf:" + s.indexOf('k' , 4 )); System.out.println("indexOf:" + s.indexOf('l' , 40 )); System.out.println("----------------------" ); System.out.println("indexOf:" + s.indexOf("owo" , 4 )); System.out.println("indexOf:" + s.indexOf("ll" , 4 )); System.out.println("indexOf:" + s.indexOf("ld" , 40 )); System.out.println("----------------------" ); System.out.println("substring:" + s.substring(5 )); System.out.println("substring:" + s.substring(0 )); System.out.println("----------------------" ); System.out.println("substring:" + s.substring(3 , 8 )); System.out.println("substring:" + s.substring(0 , s.length())); for (int i=0 ;i<s.length();i++){ System.out.println(s.charAt(i)); } } }
转换功能 1 2 3 4 5 6 7 8 9 10 11 12 13 byte [] getBytes() char [] toCharArray() static String valueOf (char [] chs) static String valueOf (int i) String toLowerCase () String toUpperCase () String concat (String str)
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public class StringDemo5 { public static void main (String[] args) { String s = "JavaSE" ; byte [] bys = s.getBytes(); for (int x = 0 ; x < bys.length; x++) { System.out.println(bys[x]); } System.out.println("----------------" ); char [] chs = s.toCharArray(); for (int x = 0 ; x < chs.length; x++) { System.out.println(chs[x]); } System.out.println("----------------" ); String ss = String.valueOf(chs); System.out.println(ss); System.out.println("----------------" ); int i = 100 ; String sss = String.valueOf(i); System.out.println(sss); System.out.println("----------------" ); System.out.println("toLowerCase:" + s.toLowerCase()); System.out.println("s:" + s); System.out.println("toUpperCase:" + s.toUpperCase()); System.out.println("----------------" ); String s1 = "hello" ; String s2 = "world" ; String s3 = s1 + s2; String s4 = s1.concat(s2); System.out.println("s3:" +s3); System.out.println("s4:" +s4); } }
练习:将一个字符串的首字母转成大写,其余为小写。(只考虑英文大小写字母字符)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class StringTest { public static void main (String[] args) { String str="helloWORLD" ; str=str.substring(0 ,1 ).toUpperCase(). concat(str.substring(1 ).toLowerCase()); System.out.println(str); } }
其他功能 1 2 3 4 5 6 7 8 9 10 11 String replace (char old,char new) String replace (String old,String new) String trim () int compareTo (String str) int compareToIgnoreCase (String str)
compareTo() 方法源码解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 private final char value[]; public int compareTo (String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0 ; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; }
练习 练习1:把数组中的数据按照指定个格式拼接成一个字符串。举例:int[] arr = {1,2,3};输出结果:[1, 2, 3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class StringTest2 { public static void main (String[] args) { int [] arr={1 ,2 ,3 ,4 }; System.out.println(arrayToString(arr)); } public static String arrayToString (int [] arr) { String str="[" ; for (int i=0 ;i<arr.length;i++){ if (i==arr.length-1 ){ str+=arr[i]; }else { str+=arr[i]+"," ; } } str+="]" ; return str; } }
练习2:统计大串中小串出现的次数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class StringTest3 { public static void main (String[] args) { String s1="woaijavawozhenaijavawozhendeaijavawozhendehenaijavaxinbuxinwoaijavagun" ; String s2="java" ; System.out.println(smallCount(s2,s1)); } public static int smallCount (String smallStr,String bigStr) { int count=0 ; int index=bigStr.indexOf(smallStr); while (index!=-1 ){ count++; int startIndex=index+smallStr.length(); bigStr=bigStr.substring(startIndex); index=bigStr.indexOf(smallStr); } return count; } }
StringBuffer 常用成员方法 1 2 3 4 5 6 7 8 9 10 11 public StringBuffer () public StringBuffer (int capacity) public StringBuffer (String str) public int capacity () public int length ()
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static void main (String[] args) { StringBuffer sb = new StringBuffer (); System.out.println("sb:" + sb); System.out.println("sb.capacity():" + sb.capacity()); System.out.println("sb.length():" + sb.length()); System.out.println("--------------------------" ); StringBuffer sb2 = new StringBuffer (50 ); System.out.println("sb2:" + sb2); System.out.println("sb2.capacity():" + sb2.capacity()); System.out.println("sb2.length():" + sb2.length()); System.out.println("--------------------------" ); StringBuffer sb3 = new StringBuffer ("hello" ); System.out.println("sb3:" + sb3); System.out.println("sb3.capacity():" + sb3.capacity()); System.out.println("sb3.length():" + sb3.length()); }
添加功能 1 2 3 4 5 public StringBuffer append (String str) public StringBuffer insert (int offset,String str)
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void main (String[] args) { StringBuffer sb = new StringBuffer (); sb.append("hello" ).append(true ).append(12 ).append(34.56 ); System.out.println("sb:" + sb); sb.insert(5 , "world" ); System.out.println("sb:" + sb); }
删除功能 1 2 3 4 5 public StringBuffer deleteCharAt (int index) public StringBuffer delete (int start,int end)
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main (String[] args) { StringBuffer sb = new StringBuffer (); sb.append("hello" ).append("world" ).append("java" ); sb.delete(0 ,sb.length()); System.out.println("sb:" + sb); }
替换功能 1 2 public StringBuffer replace (int start,int end,String str)
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static void main (String[] args) { StringBuffer sb = new StringBuffer (); sb.append("hello" ); sb.append("world" ); sb.append("java" ); System.out.println("sb:" + sb); sb.replace(5 ,10 ,"节日快乐" ); System.out.println("sb:" +sb); }
反转功能 1 public StringBuffer reverse ()
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 public static void main (String[] args) { StringBuffer sb = new StringBuffer (); sb.append("霞青林爱我" ); System.out.println("sb:" + sb); sb.reverse(); System.out.println("sb:" + sb); }
截取功能 1 2 3 public String substring (int start) public String substring (int start,int end)
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void main (String[] args) { StringBuffer sb = new StringBuffer (); sb.append("hello" ).append("world" ).append("java" ); System.out.println("sb:" + sb); String s = sb.substring(5 ); System.out.println("s:" + s); System.out.println("sb:" + sb); String ss = sb.substring(5 , 10 ); System.out.println("ss:" + ss); System.out.println("sb:" + sb); }
String 和 StringBuffer 的相互转换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class StringBufferDemo7 { public static void main (String[] args) { String s="hello" ; System.out.println(stringToStringBuffer(s)); System.out.println(stringBufferToString(stringToStringBuffer(s))); } public static StringBuffer stringToStringBuffer (String s) { StringBuffer sb2 = new StringBuffer (); sb2.append(s); return sb2; } public static String stringBufferToString (StringBuffer buffer) { String str2 = buffer.toString(); return str2; } }
练习 练习1:将数组拼接成一个字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class StringBufferTest { public static void main (String[] args) { int [] arr={1 ,2 ,3 ,4 }; System.out.println(arrToString(arr)); } public static String arrToString (int [] arr) { StringBuffer buffer=new StringBuffer (); buffer.append("[" ); for (int i=0 ;i<arr.length;i++){ if (i==arr.length-1 ){ buffer.append(arr[i]); }else { buffer.append(arr[i]).append("," ); } } buffer.append("]" ); return buffer.toString(); } }
练习2:判断一个字符串是否是对称字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class StringBufferTest2 { public static void main (String[] args) { System.out.println(isSymmetry("aba" )); System.out.println(isSymmetry2("aabbaa" )); } public static boolean isSymmetry (String s) { boolean flag=true ; char [] chs=s.toCharArray(); int len=chs.length; for (int start=0 ,end=chs.length-1 ;start<=end;start++,end--){ if (chs[start]!=chs[end]){ flag=false ; break ; } } return flag; } public static boolean isSymmetry2 (String s) { String s2=new StringBuffer (s).reverse().toString(); return s2.equals(s); } }
练习3:看程序写结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class StringBufferTest3 { public static void main (String[] args) { String s1 = "hello" ; String s2 = "world" ; System.out.println(s1 + "---" + s2); change(s1, s2); System.out.println(s1 + "---" + s2); StringBuffer sb1 = new StringBuffer ("hello" ); StringBuffer sb2 = new StringBuffer ("world" ); System.out.println(sb1 + "---" + sb2); change(sb1, sb2); System.out.println(sb1 + "---" + sb2); } public static void change (StringBuffer sb1, StringBuffer sb2) { sb1 = sb2; sb2.append(sb1); } public static void change (String s1, String s2) { s1 = s2; s2 = s1 + s2; } }
输出结果:
1 2 3 4 hello---world hello---world hello---world hello---worldworld
String作为参数传递,效果和基本类型作为参数传递是一样的。
String, StringBuffer and StringBuilder 1. 可变性
String 不可变
StringBuffer 和 StringBuilder 可变
2. 线程安全
String 不可变,因此是线程安全的
StringBuilder 不是线程安全的
StringBuffer 是线程安全的,内部使用 synchronized 进行同步
3. 性能
Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢
StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用
StringBuilder每次都会对StringBuilder对象本身进行操作,而不是生成新的对象并改变对象引用。 相同情况下使用StirngBuilder相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却冒多线程不安全的风险。
三者使用的总结
操作少量的数据,使用String
单线程操作字符串缓冲区下操作大量数据,使用StringBuilder
多线程操作字符串缓冲区下操作大量数据,使用StringBuffer