String类
String类
String用来表示一个字符串。具有以下特点:
•java.lang.String使用了final修饰,不能 被继承;
•字符串底层封装了字符数组及针对字符数组的操作算法;
•字符串一旦创建,对象永远无法改变,但字符串引用可以重新赋值;
•Java字符串在内存中采用Unicode编码方式,任何一个字符对应两个字节的定长编码。
字符串常量池
java在堆内存中开辟了一段空间用于缓存所有使用字面量形式创建的字符串对象,并在后期再次使用该字面量创建字符串时重用对象,避免内存中堆积大量内容一样的字符串对象来减小内存开销。
对于重复出现的字符串直接量,JVM会首先在常量池中查找,如果存在即返回该对象地址。
package string;
/**
* 字符串String
* 内部使用一个char数组保存所有字符,每个字符为2字节,存的是该字符unicode编码。
* 字符串是不变对象,一旦创建内容不可改变,若改变会创建新对象
*/
public class StringDemo {
public static void main(String[] args) {
/*
字符串常量池
java在堆内存中开辟了一段空间用于缓存所有使用字面量形式创建的字符串对象,
并在后期再次使用该字面量创建字符串时重用对象,避免内存中堆积大量内容一样
的字符串对象来减小内存开销。
*/
String s1 = "123abc";//字面量
String s2 = "123abc";//与s1字面量相同,重用对象
//地址相同,说明s2重用了s1对象
System.out.println(s1==s2);//true
String s3 = "123abc";
System.out.println(s1==s3);//true
String s4 = new String("123abc");//new会产生新对象
System.out.println("s4:"+s4);
System.out.println(s1==s4);//false
/*
通常我们判断字符串都是比较内容,因此应当使用字符串的equals方法
*/
System.out.println(s1.equals(s4));//true
/*
由于字符串是不变对象,改变内容会产生新对象
*/
s1 = s1 + "!";//生成一个新的字符串对象123abc!.
System.out.println("s1:"+s1);//123abc!
System.out.println("s2:"+s2);//123abc
System.out.println(s1==s2);//false s1,s2已经不再指向同一个对象了
/*
这里触发了一个编译器的特性:
编译器在编译期间若遇到几个计算表达式,发现在编译期可以确定结果时就会进行计算
并将结果编译到class文件中,这样以来JVM每次执行字节码文件就无需再计算了。
下面的代码会被编译器改为:
String s5 = "123abc";
也因此s5会重用常量池中的对象,所以地址与s2相同
*/
String s5 = "123" + "abc";
System.out.println("s5:"+s5);
System.out.println(s2==s5);
String s = "123";
String s6 = s + "abc";
System.out.println("s6:"+s6);
System.out.println(s2==s6);
String s7 = 1+2+3+"abc";//6abc
System.out.println(s2==s7);//false
String s8 = 1+'2'+3+"abc";
