字符串常量的存储位置:常量池
- 常量池中不允许存放两个相同的字符串常量,如果定义的两个字符串值相同,那么他们指向的是同一个地址
String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // true
- 常量池在jdk7版本之前是存放在方法区中的;jdk7及之后就放进了堆中。为什么会有这样一个变化?是因为堆中垃圾回收机制处理的比较频繁,而方法区中一般存放类,不会经常的垃圾回收,所以为了防止内存泄漏,就放进了堆中。
String的不可变性
- 当对字符串常量重新赋值时,是在常量池中开辟一块新空间,将新地址赋给了变量
String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // true s2 = "h1"; // 新地址 System.out.println(s1 == s2); // false
- 当对字符串常量做拼接或replace操作时,是在堆中开辟一块新空间(底层调用的是new String,则会在堆中开辟空间),将新地址赋给了变量
String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // true s2 += " world"; String s3 = s1.replace("l", "w"); System.out.println(s1); // hello System.out.println(s2); // hello world System.out.println(s1 == s2); // false System.out.println(s3); // hewwo
String s = new String("hello");
在内存中创建了2个对象
- 第一个:在堆中创建的String类型的对象
- 第二个:在字符串常量池中创建的字面量,内部存放了字符串的byte型数组
注:如果在常量池中已经存在同名的字符串,则只会创建第一个对象,然后直接指向的是那个字符串的地址值
String s1 = "hello world";与String s2 = "hello" + "world";
的区别
二者最终都指向的是常量池中的同一个地址,因为后者在编译完之后就变成前者那样了
用final
修饰的String,可以看成是一个常量,因此会在字符串常量池中直接创建
final String s1 = "hello";
String s2 = "hello world";
String s3 = s1 + " world";
System.out.println(s2 == s3); // true
String中的常用方法
-
isEmpty()
:判断字符串是否为空String s1 = ""; String s2 = new String(""); String s3 = new String(); System.out.println(s1.isEmpty()); // true System.out.println(s2.isEmpty()); // true System.out.println(s2.isEmpty()); // true
-
length()
:返回字符串的长度 -
concat(String s)
:拼接两个字符串,返回一个新字符串(会在堆中new String()
)String s1 = "hello"; String s2 = "world"; String s3 = "helloworld"; String s4 = s1.concat(s2); String s5 = "hello".concat(s2); System.out.println(s3 == s4); // false System.out.println(s3 == s5); // false System.out.println(s4 == s5); // false
-
equals(String s)
:判断两个字符串的内容是否相同,区分大小写String s1 = "hello"; String s2 = "Hello"; System.out.println(s1.equals(s2)); // false
-
equalsIgnoreCase(String s)
:判断两个字符串的内容是否相同,不区分大小写String s1 = "hello"; String s2 = "Hello"; System.out.println(s1.equalsIgnoreCase(s2)); // true
-
compareTo(String s)
:比较两个字符串的大小,按照ASCII比较,区分大小写,前者大返回正数,后者大返回负数,相同返回0;String s1 = "f"; String s2 = "ABC"; String s3 = "acd"; String s4 = "f"; System.out.println(s1.compareTo(s2)); // 37 System.out.println(s2.compareTo(s3)); // -32 System.out.println(s1.compareTo(s4)); // 0
-
compareToIgnoreCase(String s)
:与compareTo的区别是不区分大小写String s1 = "abc"; String s2 = "ABC"; System.out.println(s1.compareToIgnoreCase(s2)); // 0
-
toUppercase()和toLowerCase()
:将字符串全部转为大写/小写 -
trim()
:去除字符串前后空格 -
intern()
:返回字符串常量中的地址,存在返回地址,不存在会生成一个字面量并返回String s1 = "hello"; String s2 = "hello world"; String s3 = s1 + " world"; System.out.println(s2 == s3); // false String s4 = s3.intern(); System.out.println(s2 == s4); // true
-
contains(String s)
:判断字符串中是否包含sString s1 = "hello"; System.out.println(s1.contains("llo")); // true
-
indexOf(String s, int fromIndex)
:【从前往后】判断s在字符串中首次出现的索引位置,未找到返回-1;第二个参数是可选参数,表示从下标为fromIndex的位置开始寻找String s1 = "hello world"; System.out.println(s1.indexOf("o")); // 4 System.out.println(s1.indexOf("f")); // -1 System.out.println(s1.indexOf("o", 5)); // 7
-
lastIndexOf(String s, int fromIndex)
:【从后往前】其他与indexOf功能一致String s1 = "hello world"; System.out.println(s1.lastIndexOf("o")); // 7 System.out.println(s1.lastIndexOf("o", 6)); // 4
-
substring(int beginIndex, int endIndex)
:按照区间[beginIndex, endIndex)截取字符串,第二个参数是可选参数,不写的话,从beginIndex开始,截取到末尾String s1 = "abc123def"; System.out.println(s1.substring(3)); // 123def System.out.println(s1.substring(3, 6)); // 123
-
charAt(int index)
:取出指定索引的字符String s1 = "abcdef"; System.out.println(s1.charAt(2)); // c
-
toCharArray()
:将字符串转为char型数组String s1 = "hello"; char[] arr = s1.toCharArray(); for(int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); // h e l l o }
-
String.valueOf(char[] arr)
:将char[]转为String -
startsWith(String s, int index)
:判断字符串是否以s字符串开头的,第二个参数是可选的,表示从index索引位置开始判断是否以s字符串开头String s1 = "abcbef"; System.out.println(s1.startsWith("a")); // true System.out.println(s1.startsWith("b", 3)); // true
-
endsWith(String s)
:判断字符串是否以s字符串结束的String s1 = "hello word"; System.out.println(s1.endsWith("d")); // true
-
replace(old, new)
:将old字符或字符串替换为new,返回一个新字符串String s1 = "hello world"; System.out.println(s1.replace("wor", "QQQQQQ")); // hello QQQQQQld