Java 字符串 (String/StringBuffer/StringBuilder)

1,494 阅读2分钟
原文链接: blog.weafung.com

一、String

(一)、创建 String 对象

String str1 = new String("Hello World!");   //方法一
String str2 = "Hello World!";    //方法二
......

(二)、两种方法的坑

代码

String str1 = new String("Hello World!");
String str2 = "Hello World!";
if (str1 == str2) {
    System.out.println("str1 == str2");
} else {
    System.out.println("str1 != str2");
}
String str3 = "Hello World!";
if (str2 == str3) {
    System.out.println("str2 == str3");
} else {
    System.out.println("str2 != str3");
}

输出

str1 != str2
str2 == str3

原因

两个语句都是返回一个String对象的引用, 但JVM处理的方式不一样.

方法一: JVM 马上在堆区中创建String对象, 然后将对象的引用返回.(并不会添加至 String Pool 中, 除非显示的调用 Stringintern方法)

方法二: JVM 首先在 String Pool 中通过Stringequals 方法查找对象池中是否有该String对象. 如果有,则直接返回而不会再重新创建; 如果没有, JVM 则在堆区中创建新的String对象, 将其引用返回, 同时将该引用添加至String Pool中.

String Pool不是在堆区,也不是在栈区,而是存在于方法区(Method Area)

(三)、常用的一些方法

String str = new String("Hello World!");
System.out.println(str.length());
System.out.println(str.substring(0, 5));
System.out.println(str.charAt(0));
System.out.println(str.equals("Hello World!"));
System.out.println(str.compareTo("Hello World!"));
System.out.println(str.replaceAll("o", "O"));
System.out.println(str.toLowerCase());
System.out.println(str.hashCode());
System.out.println(str.concat("Hahahaha!"));

(四)、hashCode 的实现

根据以下公式计算:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

(s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。空字符串的哈希值为 0)

(五)、不可变对象

String 对象是不可变对象, 创建后就不可修改.

优势

  • 安全( String Pool / 多线程)
  • 效率

二、StringBuffer

(一)、使用

StringBuffer stringBuffer = new StringBuffer("Hello");
System.out.println(stringBuffer);

stringBuffer.append("world!");
System.out.println(stringBuffer);

stringBuffer.reverse();
System.out.println(stringBuffer);

stringBuffer.delete(0, 1);
System.out.println(stringBuffer);

stringBuffer.reverse();
stringBuffer.insert(5, " ");
System.out.println(stringBuffer);

stringBuffer.replace(5, 11, "OOO");
System.out.println(stringBuffer);
stringBuffer.trimToSize();
Hello
Helloworld!
!dlrowolleH
dlrowolleH
Hello world
HelloOOO

(二)、错误的初始化方式

StringBuffer s = “abc”;               //赋值类型不匹配
StringBuffer s = (StringBuffer)”abc”;    //不存在继承关系,无法进行强转

(三)、与String对象之间的互转

String s = "abc";
StringBuffer sb1 = new StringBuffer("123");
StringBuffer sb2 = new StringBuffer(s);   //String转换为StringBuffer
String s1 = sb1.toString();              //StringBuffer转换为String

三、StringBuilder

使用

StringBuilder sbuilder = new StringBuilder();
......

四、三角关系

(一)、关系图

...

(二)、区别

  • String 继承于CharSequence,也就是说String也是CharSequence类型

  • StringBuilderStringBuffer都是可变的字符序列。它们都继承于AbstractStringBuilder,实现了CharSequence接口

  • String是不可变的,StringBufferStringBuilder是可变的

  • StringBuilder是非线程安全的,而String(不可变对象)、StringBuffer(对方法加了同步锁或者对调用的方法加了同步锁)是线程安全的

  • StringBuilder适用于单线程环境,StringBuffer适用于多个线程操作同一个字符串

  • 大部分情况下: StringBuilder > StringBuffer > String

五、参考

Weafung原创。Weafung's Homepage | Weafung's Blog

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。