java中的字符串常量比较的特殊,它可以直接赋值给字符串类型的变量:String str = "hello world"。字符串常量自己就可以像String对象一样调用String类中定义的方法。实际上这些字符串常量本身就是字符串对象,在内存中它们被保存在一个共享的区域,这个地方被称为字符串常量池,每个常量只会保存一份被所有的使用者共享。
public static void main(String[] args){ String str1="hello world"; String str2="hello world"; System.out.println(str1==str2); //true }
上面的代码其实只是创建了一个String对象,两个变量都指向同一个String对象所以str1==str2返回的是true。如果使用new String("hello world")来创建对象那么str1==str2就不会返回true了,代码如下:
public static void main(String[] args) { String str1 = new String("hello world"); String str2 = new String("hello world"); System.out.println(str1==str2); //false System.out.println(str1.equals(str2)); //true System.out.println(str1.hashCode()==str2.hashCode());//true }
可以看出str1和str2指向了两个不同的对象,但是这两对象的值是相等的,所以他们的hashcode值也是相等的。
在java中由于String是不可变的所以当我们需要频繁的修改字符串时通常使用StringBuilder类和StringBuffer类,其中StringBuilder是线程不安全的,StringBuffer是线程安全的。在我们平时的开发中,字符串对象及其操作在大部分情况下都是线程安全的所以我们通常使用StringBuilder类来创建字符串对象。例如:
public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("hello"); sb.append(",world"); System.out.println(sb.toString()); }
使用StringBuild类创建String对象首先需要创建一个StringBuilder对象然后使用append(String str)方法拼接字符串,最后调用StringBuild对象的toString()方法返回字符串。
在java中我们也经常使用“+”和“+=”运算符来创建字符串。例如:
public static void main(String[] args) { String str = "hello"; str += " world"; System.out.println(str); //hello world }
背后其实java编译器会将其转换成StringBuilder来处理:
public static void main(String[] args) { StringBuilder hello = new StringBuilder("hello"); hello.append(" world"); System.out.println(hello.toString()); }
所以当我们使用“+=”创建字符串时ava编译器会帮我们使用StringBuilder类来优化。但是如果在一些稍微复杂的场景下建议还是自己手动的使用StringBuilder类来创建字符串。