文章目录
字符串
1. String类
- Java程序中的所有字符串字面值都作为此类的实例实现
- String是一个final类,代表不可变的字符序列
- 字符串是常量,用双引号引起来表示,它们的在创建之后不能更改
- String对象的字符内容是存储在一个字符数组value[]中的,该数组被final修饰
String类的部分源码:
// 声明为final的,表示String不可被继承,
// 实现了Serializable接口,表示字符串是支持序列化的
// 实现了Comparable接口,表示字符串是支持比较大小的
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[]; // value用于存储字符串数据的
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;
注意:
- 对字符串重新赋值时,会在字符串常量池中重新开辟一块空间进行赋值,不能使用原有的value进行赋值
- 当对现有的字符串进行连接操作时,也需要重新指定内存区域进行赋值
- 当调用repalce()方法修改字符/字符串时,也必须重新指定内存区域进行赋值
2. String对象的创建
String str = "helloWorld";
String str = new String(); // 等同于 char[] value = new char[0] ;
String str = new String(String original) ; // 等同于this.value = original.value
String str = new String(char[] a) ; // 等同于 this.value = Arrays.copyOf(value, value.length)
String str = new String(char[] a, int startIndex, int count) ;
3.对字符串进行 == 测试
(1) 比较字面常量创建的字符串
String s1 = "Hello World";
String s2 = "Hello World";
String s3 = s1+"...";
System.out.println("(s1 == s2) = " + (s1 == s2)); // true
System.out.println(s2);// Hello World
System.out.println(s3); // Hello World...
- 由字符串字面常量方式直接创建的字符串,两个相同字符串引用的相同
- 对原本存在的字符串进行拼接操作时,并不是在原有的字符串上进行修改,而是新创建一个字符串
(2) 比较字面常量创建的字符串和关键字new创建的字符串
String str1 = "javaEE";
String str2 = new String("javaEE");
String str3 = new String("javaEE");
System.out.println("(str2 == str3) = " + (str2 == str3)); // false:使用new关键字创建的字符串存储在堆中,因此,两个引用的不相同
System.out.println("(str1 == str3) = " + (str1 == str3)); // false:常量池和堆不在同一区域
System.out.println("(str1 == str2) = " + (str1 == str2)); // false
- 使用new关键字创建的字符串对象存放在堆中
- 常量池和堆不在同一内存空间
- 使用new创建字符串时,例如
String str = new String("java");
使用关键在new创建字符串和使用字面常量创建字符串的区别:
- 字符串常量创建字符串对象存储在字符串常量池中,用于共享
- 使用new关键字创建的字符串对象存储在堆中
- 待补充
*[java中堆、栈、常量池的区别]
(3) 对对象成员变量字符串的测试
public class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
// 对象的成员变量中字符串是否为同一个引用:
Person p1 = new Person("jack", 15);
Person p2 = new Person("jack", 15);
String name = "jack";
System.out.println("(p1.name == p2.name) = " + (p1.name == p2.name)); // true
System.out.println("(p1.name == name) = " + (p1.name == name)); // true
p1.name = "mary";
System.out.println("(p1.name == p2.name) = " + (p1.name == p2.name)); // false
}
}
- 使用同一个字符串常量进行赋值,因此两个对象的成员变量的引用都指向常量池中的该字符串
(4) 对字符串拼接运算的测试
// 对字符串拼接运算的测试
String string1 = "soul_goodman";
String string2 = "lawyer";
String string3 = "soul_goodmanlawyer";
String string4 = "soul_goodman" + "lawyer";
String string5 = string1+"lawyer";
String string6 = "soul_goodman" +string2;
String string7 = string1+string2;
System.out.println("(string3 == string4)= " + (string3 == string4));// ture
System.out.println("(string3 == string5)= " + (string3 == string5));// ture
System.out.println("(string3 == string6)= " + (string3 == string6));// ture
System.out.println("(string3 == string7)= " + (string3 == string7));// ture
运行结果:
(string3 == string4)= true
(string3 == string5)= false
(string3 == string6)= false
(string3 == string7)= false
- 拼接运算中对两个字面常量进行拼接的结果存放在字符串常量池中
- 如果进行拼接时存在一个变量,则拼接的结果存放在堆中
(5) String类的intern()方法
String str = string7.intern();
System.out.println("(string3==str) = " + (string3 == str));
- 调用String类的intern()方法,返回的字符串为字符串常量池中的字符串
验证:
String str_1 = new String("breaking_bad").intern();
String str_2 = "breaking_bad";
System.out.println("(str_1==str_2) = " + (str_1 == str_2)); // true
(6) 字符串做为方法参数
public class StringTest {
public static void main(String[] args) {
String unchanged = "unchanged";
char[] chars = {'D','o','v','e'};
StringTest(unchanged,chars);
System.out.println(unchanged); // unchanged
System.out.println(String.valueOf(chars));// Love
}
public static void StringTest(String str,char[] chars ){
str = "changed";
chars[0] = 'L';
}
}
值传递和引用传递:
- 值传递:实参将自己的值传递给对应的形参,方法内改变形参时不会改变实参的值;基本数据类型采用的是值传递
- 引用传递:实参将自己的引用传递给对应的形参,方法内更改形参时会改变实参的值;对象的传递改用的是引用的传递
- java中对于String的传递采用的是引用传递,但由于字符串具有不可变性,即使形参的值改变了,但并不影响实参的值
4. String类常用方法
String str = "HelloWorld";
- length()
- charAt() 返回指定索引位置的字符
System.out.println("str.charAt(5) = " + str.charAt(5)); // str.charAt(5) = W
- isEmpty() 判断字符串是否为空(长度为0)
System.out.println("\"\".isEmpty() = " + "".isEmpty());// "".isEmpty() = true
- toLowerCase() 将字符串全部转换成小写
String str2 = str.toLowerCase();
System.out.println("str = " + str);// str = HelloWorld 字符串的不可变性
System.out.println("str2 = " + str2); // str2 = helloworld
- toUpperCase() 将字符串全部转换成大写
- trim() 去除字符串中首尾的空格
String str3 = " h e l l o worl d ";
String str4 = str3.trim();
System.out.println("-------------" + str3 + "-------------");
System.out.println("-------------" + str4 + "-------------");
运行结果:
------------- h e l l o worl d -------------
-------------h e l l o worl d-------------
- equals()
- equalsIngnoreCase() 忽略大小写的情况下下比较两个字符串是否相等
System.out.println("str.equalsIgnoreCase(str2) = " + str.equalsIgnoreCase(str2)); // str.equalsIgnoreCase(str2) = true
- concat() 拼接两个字符串,等同于 +
- 10.compareTo() 比较两个字符串大小,该方法涉及到字符串排序(比较器的实现)
System.out.println("str.compareTo(str3) = " + str.compareTo(str3)); // 'H':72, ' ':32
- substring() 返回字符串的子字符串
System.out.println("str.substring(5) = " + str.substring(5)); // str.substring(5) = World
System.out.println("str.substring(5,8) = " + str.substring(5, 8)); // 不包括8 str.substring(5,8) = Wor
- endsWith(String suffix) 测试此字符串是否以指定后缀结束
System.out.println("str2.endsWith(\"ld\") = " + str2.endsWith("ld")); // true
- startsWith(String prefix) 测试此字符串是否以指定前缀开始
System.out.println("str.startsWith(\"He\") = " + str.startsWith("He")); // str.startsWith("He") = true
- startsWith(String prefix, int toffset) 测试此字符串 从指定索引开始的子字符 是否以指定前缀开始
System.out.println("str.startsWith(\"Wo\",5) = " + str.startsWith("Wo",5 )); str.startsWith("Wo",5) = true
- contains() 判断一个字符串中是否包含某子字符串
System.out.println("str.contains(\"orld\") = " + str.contains("orld")); // str.contains("orld") = true
- indexOf() 判断一个字符串中指定子字符串/字符首次出现的位置
System.out.println("str.indexOf(\"lo\") = " + str.indexOf("lo")); //str.indexOf("lo") = 3
System.out.println("str.indexOf(\"lo\",5) = " + str.indexOf("lo",5)); // str.indexOf("lo",5) = -1
- lastIndexOf() 判断一个字符串中指定字符串/字符从右往左首次出现的位置
System.out.println("str.lastIndexOf(\"ol\") = " + str.lastIndexOf("ol"));
- replace() 将当前字符串中的某个字符/字符串替换成指定字符串
System.out.println("str.replace(\"Hello\",\"AV\") = " + str.replace("Hello","AV"));
System.out.println("str.replace('H','B') = " + str.replace('H','B'));
- replaceAll() 正则表达式,给定的replacement替换一个字符串中的某些指定值
- matches() 正则表达式,判断一个字符串是否符合给定的条件
- spilt() 对字符串进行切片操作
5. String类与基本数据类型包装器的转化
(1)将字符串转化成某种基本数据类型
- 调用包装器的静态方法:
baseType varName = typeWrapper.parseType(String);
- 例如:将字符串"123"转换成整数
String _123 = "123";
int num = Integer.parseInt(_123);
System.out.println("num = " + num);
(2)将某种基本数据类型转化成字符串
- 调用String重载的valueOf()
String num = String.valueOf(123);
- 例如:将整数123转化成字符串
int item = 123 ;
String num = String.valueOf(item);
System.out.println("num = " + num);
6. 字符串与char[]的转化
(1)字符数组转换成字符串
- 调用String类的静态方法valueOf()
char[] chars = {'B','r','e','a','k','i','n','g',' ','b','a','d'};
String newString = String.valueOf(chars);
System.out.println("newString = " + newString);
- 通过String类的构造器
char[] chars = {'B','r','e','a','k','i','n','g',' ','b','a','d'};
String newString = new String(chars);
System.out.println("newString = " + newString);
(2)将字符串转换成字符数组
- 调用被转换字符串的toCharArray()方法
String str = "Breaking bad";
char[] chars = str.toCharArray();
7. 字符串与字节数组的转换
(1)字符串转换成字节数组
- 调用被转换字符串对象的getBytes()
String soul = "soul_goodMan";
byte[] bytes = soul.getBytes(); // 使用默认的字符集进行转换(编译器设置的默认的字符集)
System.out.println(Arrays.toString(bytes));
byte[] gbk_bytes = lawyer.getBytes("gbk"); // 指定使用的字符集进行转换
System.out.println(Arrays.toString(gbk_bytes) );
运行结果:
bytes[-23, -93, -114, -23, -86, -102, -27, -66, -117, -27, -72, -120, 58, 115, 111, 117, 108, 95, 103, 111, 111, 100, 77, 97, 110]
gbk_bytes[-73, -25, -55, -89, -62, -55, -54, -90, 58, 115, 111, 117, 108, 95, 103, 111, 111, 100, 77, 97, 110]
(2)字节数组转换成字符串
- 将字节数组作为参数传递给String类的构造器从而转换成字节数组
String aLawyer_1 = new String(bytes); // 使用默认字符集,进行解码
System.out.println(aLawyer_1);
String aLawyer_2 = new String(gbk_bytes,"gbk"); // 指定字符集进行解码,如果解码的字符集与编码的字符集不同会导致乱码
System.out.println(aLawyer_2);