1. 创建字符串
String str1 = "Hello world";
String str2 = new String("Hello World");
char[] array = {'a','b','c'};
String str3 = new String(array);
2. 字符串比较
2.1 equals()
==是用来比较地址的,想要比较两个字符串内容是否相等,要使用函数equals();
String str1 = "Hello";
Stirng str2 = "hello";
System.out.println(str1.equals(str2));
System.out.println(str2.equals(str1));
注意事项:
- 比较函数equals()是区分大小写的比较;
- 当比较两者不为null时,上述两种写法均可;但如果str1 = null,null值引用方法会报错,所以使用方法2更安全。
2.2 equalsIgnoreCase()
与equals()方法类似,是不分区大小写的比较方法。
2.3 compareTo()
int compareTo(String anotherString):按字典顺序比较两个字符串
返回值为int,从第一个字符开始比较两个字符串,
如果不相等,返回两者的ASCII差值;
如果相等就比较第二个,以此类推,直到不等为止,或str1与str2长度不同,但对应位字符相同,此时返回长度差。
public static void main(String[] args) {
String str1 = "Stringa";
String str2 = "Stringc";
String str3 = "Stringa1234";
int result1 = str1.compareTo(str2);
System.out.println(result1);
int result2 = str1.compareTo(str3);
System.out.println(result2);
}
2. 字符串常量池
2.1 共享设计模式
String类的设计使用了共享设计模式,在JVM底层实际上会自动维护一个对象池(字符串常量池)。
a)直接赋值法
- 若采用直接赋值法创建字符串,将该实例化对象,即字符串内容保存在字符串常量池中。例如str1。
- 若下次使用直接赋值法创建字符串,在字符串常量池中已有指定内容,那么直接进行引用,无需再开辟新的空间。
b)构造方法
- 若采用String构造方法会在堆内存中开辟出两块内存空间,其中一块会成为垃圾空间。
- 只要是构造方法new出来的对象都是要再堆中开辟空间的,所以会出现同一字符串可能被存储多次,浪费时间。例如str2。
c) 拼接字符串
- 若拼接两者均字符串常量,那么拼接后的字符串与源字符串变量视为相同变量,公用一个内存地址。例如str3。
- 只要有其一为变量或是new出来的字符串,那么拼接时会new新的字符串存在堆上。例如str6、str7。
2.2 内存结构分析
String str1 = "Hello";
String str2 = new String("Hello");
String str3 = "He"+"llo";
String str4 = "He";
String str5 = "llo";
String str6 = str4 + str5;
String str7 = "He"+ new String("llo");
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str1 == str6);
System.out.println(str1 == str7);
面试题:请解释String类中两种对象实例化的区别?
A: 直接赋值法:只会开辟一块堆内存,并且该字符串对象可以自动保存再字符串常量池中以供下次使用。 构造方法:会在堆内存中开辟出两块内存空间,且一块作为垃圾空间,不会自动保存再字符串常量池中,可以手动入池。
2.3 手动入池
在使用构造函数创建字符串时,字符串内容不会自动保存再字符串常量池中,所以可以采用intern()方法手动入池。
String str1 = "Hello";
String str2 = new String("Hello").intern();
System.out.println(str1 == str2);
3. 字符串与字符转换
String str = "hello world";
System.out.println(str.charAt(0));
String str = "hello wordl";
char[] array = str.toCharArray();
char[] array = {'a','b','c'};
String str1 = new String(array);
String str2 = new String(array,0,1);
4. 字符串不可变
字符串是一种不可变对象,它的内容不可改变。
例如下述代码,修改前str1和str2都指向同一块内存地址,但是修改后,str1指向"world"所在的新地址,而str2还指向原来的“hello”的地址,所以不再指向同一个地址。由此可见,字符串修改,本质上是是该引用指向了新的对象,而不是对原对象的修改。
public static void main(String[] args) {
String str1 = "hello";
String str2 = str1;
System.out.println(str1);
System.out.println(str2);
System.out.println(str1 == str2);
System.out.println("============");
str1 = "world";
System.out.println(str1);
System.out.println(str2);
System.out.println(str1 == str2);
}
|