String
- String类右称作不可变字符串序列
- String位于java.lang包中
- Java字符串时Unicode字符序列, 例如字符组"Java就是4个Unicode字符
J
,a
,v
,a
组成 - Java没有内置字符串类型, 而是在标准Java库中提供了一个预定义的String类, 每个用双引号括起来的字符串都是String类的一个实例
- Java允许使用
+
把两个字符串连接起来
+
两侧操作数中, 只要有一个是字符串类型(String), 系统会自动将另一个操作数转换为字符串, 然后再进行连接, 双引号没有字符也是字符串类型
+
把两个字符串按给定的顺序连接在一起, 并且是完全按照给定的形式连接, 连接时会在编译期间发生. 因此, 在使用==进行String对象之间的比较时, 需特别注意
/********************字符串拼接时的优化**************************/
public static void main(String[] args) {
// 编译器做了优化, 直接在编译时将字符串进行拼接
String str1 = "hello" + " java"; // 相当于str1 = "hello java"
String str2 = "hello java";
System.out.println(str1 == str2);
String str3 = "hello";
String str4 = " java";
// 编译的时候不知道变量中存储的是什么, 所以没有办法在编译的时候优化
String str5 = str3 + str4;
System.out.println(str2 == str5);
// 字符串比较时使用equals, 而不是== !!!
System.out.println(str2.equals(str5));
}
/*
true
false
true
*/
字符串相等的判断
equals方法用来检测两个字符串内容是否相等
测试两个字符串除了大小写区别外是否想的相等, 需要使用equalsIgnoreCase方法
判断两个字符串是否相等不要使用==
public class TestString {
public static void main(String[] args) {
String str1 = "abc";
String str2 = new String("haha");
// 自动把13转换为String类型
String str3 = 13 + "";
int i = 1;
System.out.println("###############分隔符##############");
System.out.println(str1 + " " + str2);
System.out.println("str3自动转换为String类型" + str3);
System.out.println("" + i);
System.out.println("###############分隔符##############");
String str4 = "zyb";
String str5 = "zyb";
String str6 = new String("zyb");
String str7 = new String("zYb");
System.out.println(str4 == str5); // str4和str5是同一个对象
System.out.println(str4 == str6); // str4和str6不是同一个对象
System.out.println("###############分隔符##############");
System.out.println("比较内容是否相同: " + str4.equals(str6)); // str4和str6内容相同
System.out.println("忽略大小写比较: " + str4.equalsIgnoreCase(str7)); // str4和str6内容相同
}
}
/*
###############分隔符##############
abc haha
str3自动转换为String类型13
1
###############分隔符##############
true
false
###############分隔符##############
比较内容是否相同: true
忽略大小写比较: true
*/
字符串常用方法
public class StringTest {
public static void main(String[] args) {
String s1 = "core Java";
String s2 = "Core Java";
System.out.print("取下标为3的字符: ");
System.out.println(s1.charAt(3));
System.out.print("字符串的长度: ");
System.out.println(s2.length());
// 注意下标范围
System.out.print("截取第2到第3个字符: ");
System.out.println(s1.substring(2, 4));
System.out.print("比较两个字符串是否相等: ");
System.out.println(s1.equals(s2));
System.out.print("忽略大小写比较两个字符串是否相等: ");
System.out.println(s1.equalsIgnoreCase(s2));
System.out.print("字符串s1中是否包含Java, 返回索引: ");
System.out.println(s1.indexOf("Java"));
System.out.print("字符串s1中是否包含apple: ");
System.out.println(s1.indexOf("apple"));
// 将s1中的空格替换成&
String s = s1.replace(' ', '&');
System.out.print("替换后字符串为: ");
System.out.println(s);
System.out.print("是否以core开头: ");
System.out.println(s1.startsWith("core"));
System.out.print("是否以core开头: ");
System.out.println(s2.startsWith("core"));
System.out.print("是否以java结尾");
System.out.println(s1.endsWith("java"));
System.out.print("提取子字符串, 从下标2开始到字符串结尾为止: ");
System.out.println(s1.substring(2));
System.out.print("提取子字符串, [2, 5), 包括2, 不包括5: ");
System.out.println(s1.substring(2, 5));
System.out.print("转换为小写: ");
System.out.println(s1.toLowerCase());
System.out.print("转换为大写: ");
System.out.println(s1.toUpperCase());
String s3 = " How are you? "; // H前面退格符, ?后为空格
System.out.print("去除字符串首位的空格/退格(中间空格不能去除):");
System.out.println(s3.trim());
System.out.print("由于String是不可变字符串类型, 所有s3不变: ");
System.out.println(s3);
}
}
/*
取下标为3的字符: e
字符串的长度: 9
截取第2到第3个字符: re
比较两个字符串是否相等: false
忽略大小写比较两个字符串是否相等: true
字符串s1中是否包含Java, 返回索引: 5
字符串s1中是否包含apple: -1
替换后字符串为: core&Java
是否以core开头: true
是否以core开头: false
是否以java结尾false
提取子字符串, 从下标2开始到字符串结尾为止: re Java
提取子字符串, [2, 5), 包括2, 不包括5: re
转换为小写: core java
转换为大写: CORE JAVA
去除字符串首位的空格/退格(中间空格不能去除):How are you?
由于String是不可变字符串类型, 所有s3不变: How are you?
*/
使用陷阱
String一经初始化后, 就不会再改变其内容. 对String字符串的操作实际上就是对其副本(原始拷贝)的操作, 原来的字符串一点都没有改变
String s = "a"; s = s + b
实际上原来的"a"字符对象已经丢弃, 现在有产生了另一个字符串s + "b"
即ab
. 如果多次执行这些改变字符串内容的操作, 会导致大量副本字符串对象留在内存中, 降低效率. 如果这样的操作放到循环中, 会极大的影响程序的运行时间和空间性能, 甚至会造成服务器崩溃