JAVA中的String类是用于存储字符串数据的,C语言中没有String类型,C语言中使用char[]数组存储字符串。
本文涉及JVM的内存划分,不了解的读者可看JVM——Java虚拟机-CSDN博客
JAVA中的String对象是不可变的。注意,这里说的不可变不是字符串的引用不可变,而是字符串本身不可变。以下面的代码为例:
public static void main(String[] args) {
String s1 = "Hello world!";
s1 = "xixi";
System.out.println(s1);
}
当执行 String s1 = "Hello world!" 时:
- JVM 会检查常量池,如果没有 "Hello world!",就会在常量池中创建该字符串对象
- 让 s1 引用指向常量池中的 "Hello world!" 对象
当执行 s1 = "xixi" 时:
- JVM 会检查常量池,如果没有 "xixi",就会在常量池中创建该字符串对象
- 让 s1 引用指向常量池中的 "xixi" 对象(原来的 "Hello world!" 对象仍然在常量池中)
这样做的好处就是后面一旦再有一个String对象以常量池中有的值进行初始化,就不必再开辟额外的空间了,提高了内存复用。
一.String类的比较
直接使用==进行比较的话,比较的是两个引用是否相等,即地址是否相同。与其他类不同的一点在于,由于常量池的存在,直接使用字符串对String引用进行初始化,引用指向的地址会是同一块。以代码为例:
public static void main(String[] args) {
Student s1 = new Student("zhangsan",10);
Student s2 = new Student("zhangsan",10);
System.out.println(s2==s1);//false
String s3 = new String("haha");
String s4 = new String("haha");
System.out.println(s3==s4);//false
String s5 = "haha";
String s6 = "haha";
System.out.println(s5==s6);//true
}
结果:
s3与s4由于new了两个新对象,这两个对象存储在堆上。两块不同的地址,引用自然不同。
s5和s6直接引用了常量池中的数据,因此引用值相同,都储存“haha”所在常量池的地址。
我们可以使用intern()方法来将字符串放进常量池中。
public static void main(String[] args) {
char[]ch = new char[]{'a','b','c'};
String s1 = new String(ch);
//s1.intern();
String s2 ="abc";
System.out.println(s1 == s2);
}
这个代码输出结果为false,一旦解开注释intern(),结果就为true。因为s1引用的值被放进了常量池。
二.String类的常用方法
一、获取字符串信息
length() 返回字符串的长度(字符个数)。
String s = "hello";
System.out.println(s.length()); // 输出:5
charAt(int index) 返回指定索引位置的字符(索引从 0 开始)。
String s = "hello";
System.out.println(s.charAt(1)); // 输出:'e'
indexOf(String str) 返回子字符串 str 在当前字符串中第一次出现的索引,若不存在则返回 -1。
String s = "hello world";
System.out.println(s.indexOf("lo")); // 输出:3
lastIndexOf(String str) 返回子字符串 str 在当前字符串中最后一次出现的索引,若不存在则返回 -1。
String s = "hello world";
System.out.println(s.lastIndexOf("o")); // 输出:7
二、字符串比较
equals(Object obj) 比较两个字符串的内容是否相等(区分大小写)。
String s1 = "hello";
String s2 = "Hello";
System.out.println(s1.equals(s2)); // 输出:false
equalsIgnoreCase(String str) 比较两个字符串的内容是否相等(不区分大小写)。
String s1 = "hello";
String s2 = "Hello";
System.out.println(s1.equalsIgnoreCase(s2)); // 输出:true
compareTo(String str) 按字典顺序比较两个字符串(返回整数:正数表示当前字符串更大,负数表示更小,0 表示相等)。
String s1 = "apple";
String s2 = "banana";
System.out.println(s1.compareTo(s2)); // 输出:负数('a' < 'b')
三、字符串修改(返回新字符串,原字符串不变)
concat(String str) 将当前字符串与 str 拼接,返回新字符串(等效于 + 运算符)。
String s = "hello".concat(" world");
System.out.println(s); // 输出:"hello world"
substring(int beginIndex) 从 beginIndex开始截取子字符串,直到末尾。
String s = "hello world";
System.out.println(s.substring(6)); // 输出:"world"
substring(int beginIndex, int endIndex) 截取 [beginIndex, endIndex) 范围内的子字符串(包含开始,不包含结束)。
String s = "hello world";
System.out.println(s.substring(0, 5)); // 输出:"hello"
toLowerCase() / toUpperCase() 将字符串转换为全小写 / 全大写,返回新字符串。
String s = "Hello World";
System.out.println(s.toLowerCase()); // 输出:"hello world"
System.out.println(s.toUpperCase()); // 输出:"HELLO WORLD"
trim() 去除字符串首尾的空白字符(空格、换行、制表符等),返回新字符串。
String s = " hello ";
System.out.println(s.trim()); // 输出:"hello"
replace(char oldChar, char newChar) 将字符串中所有 oldChar 替换为 newChar,返回新字符串。
String s = "hello";
System.out.println(s.replace('l', 'x')); // 输出:"hexxo"
replace(CharSequence target, CharSequence replacement) 替换所有匹配的子字符串 target 为 replacement。
String s = "hello world";
System.out.println(s.replace("world", "java")); // 输出:"hello java"
四、其他常用方法
split(String regex) 根据正则表达式 regex 分割字符串,返回字符串数组。
String s = "apple,banana,orange";
String[] parts = s.split(","); // 按逗号分割
// parts 结果:["apple", "banana", "orange"]
startsWith(String prefix) 判断字符串是否以 prefix 开头(返回 boolean)。
String s = "hello world";
System.out.println(s.startsWith("hello")); // 输出:true
endsWith(String suffix) 判断字符串是否以 suffix 结尾(返回 boolean)。
String s = "hello world";
System.out.println(s.endsWith("world")); // 输出:true
isEmpty() 判断字符串是否为空(长度为 0,返回 boolean)。
String s = "";
System.out.println(s.isEmpty()); // 输出:true
valueOf(…)(静态方法) 将其他类型(如 int、double、Object 等)转换为字符串。
String s1 = String.valueOf(123); // "123"
String s2 = String.valueOf(true); // "true"
评论前必须登录!
注册