一、String 类的特点
- Java 程序中所有双引号字符串,都是 String 类的对象。
- 字符串在创建之后,其内容不可更改。
如果想要更改,只能使用新的对象做替换。 - 字符串虽然不可改变,但是可以被共享。
在使用双引号创建字符串对象时,会检查字符串常量池中是否存在该对象,如果不存在则创建对象,如果存在则复用该对象。
二、String 类常见构造方法
1、public String ( ):创建一个空白字符串,里面不含任何内容
String s1 = new String();
2、public String (char[ ] chs):根据传入的字符串数组,创建字符串对象
char[] chs = {'a', 'b', 'c'};
String s1 = new String(chs); //此时对象s1为abc
3、public String (String original):根据传入的字符串,来创建字符串对象
String s1 = new String("abc"); //此时对象s1为abc
三、内存分析
实例1:
1、StringTest1类的字节码文件进入方法区。
2、主方法被虚拟机调用进入栈内存,随后执行主方法中的语句。
3、声明一个字符串对象 s1,等号右边使用双引号创建字符串变量 “abc” ,在创建字符串变量的时候,检查堆内存中字符串常量池中是否存在该字符串变量,发现并不存在,所以创建该变量,随后将 “abc” 变量的地址交给字符串对象 s1。
4、继续声明一个字符串对象 s2,等号右边使用双引号创建字符串变量 “abc” ,同理,也要进入字符串常量池中检查是否存在该对象,发现已经存在,则直接复用,所以字符串对象 s2 也是记录着变量 “abc” 的地址。
5、对象 s1 和对象 s2 都记录着相同的地址,所以打印输出为 true。
实例2:
1、StringTest1类的字节码文件进入方法区。
2、主方法被虚拟机调用进入栈内存,随后执行主方法中的语句。
3、声明一个字符串对象 s1,等号右边使用双引号创建字符串变量 “abc” ,在创建字符串变量的时候,检查堆内存中字符串常量池中是否存在该字符串变量,发现并不存在,所以创建该变量,随后将 “abc” 变量的地址交给字符串对象 s1。
4、继续声明一个字符串对象 s2,等号右边出现了 new,注意此时应在堆内存中另外开辟一个独立空间,同时也有使用双引号创建字符串变量 “abc”,同理,也要进入字符串常量池中检查是否存在该对象,发现已经存在,则直接复用,将字符串常量池中字符串变量 “abc” 的地址拷贝一份交给 new 开辟的空间,最后将 new 开辟空间的地址交给字符串对象 s2。
5、对象 s1 和对象 s2 记录着不同的地址,所以打印输出为 false。
注意:new String(“abc”) 该语句创建了两个字符串变量,一个是 new 创建的,在堆内存中有自己独立的空间,另一个是双引号创建的,该字符串变量在字符串常量池中进行维护。
实例3:
1、StringTest1类的字节码文件进入方法区。
2、主方法被虚拟机调用进入栈内存,随后执行主方法中的语句。
3、声明一个字符串对象 s1,等号右边使用双引号创建字符串变量 “abc” ,在创建字符串变量的时候,检查堆内存中字符串常量池中是否存在该字符串变量,发现并不存在,所以创建该变量,随后将 “abc” 变量的地址交给字符串对象 s1。
4、继续声明一个字符串对象 s2,等号右边使用双引号创建字符串变量 “ab” ,在创建字符串变量的时候,检查堆内存中字符串常量池中是否存在该字符串变量,发现并不存在,所以创建该变量,随后将 “ab” 变量的地址交给字符串对象 s2。
5、继续声明一个字符串对象 s3,等号右边存在使用双引号创建字符串变量 “c”,同理,检查堆内存中字符串常量池中是否存在该字符串变量,发现并不存在,所以创建该变量。字符串的 + 号拼接会自动创建 StringBuilder 对象以及空间,然后调用该对象中的字符串拼接方法,将字符串变量 s2 和字符串变量 “c” 在该块空间进行字符串的拼接,拼接完以后由于类型不统一,又再调用 StringBuilder 对象里面的 toString 方法,将对象类型转换为 String 类型,最后将新生成的空间地址交给字符串对象 s3。
6、对象 s1 和对象 s2 记录着不同的地址,所以打印输出为 false。
实例4:
根据常量优化机制,字符串对象 s2 的内容在编译时的字节码文件中已经拼接为字符串变量 “abc”,所以此时该题已经转化为实例1,所以打印输出为 true。
四、String 类常用方法
1. 字符串比较内容
String 类用于比较的方法:
- public boolean equals(要比较的字符串)
完全一样结果才是 true,否则为 false - public boolean equalsIgnoreCase(要比较的字符串)
忽略大小写的比较
案例:用户登录
需求:已知正确的用户名和密码,请用程序实现模拟用户登录。总共3次机会,登录后给出相应提示。
import java.util.Scanner;
public class TestDemo01 {
public static void main(String[] args) {
//定义两个字符串类型变量,模拟已经存在的用户名和密码
String username = "Benjieming";
String password = "123456";
for (int i = 1; i <= 3; i++) {
//键盘录入用户输入的用户名,密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String scannerusername = sc.nextLine();
System.out.println("请输入密码:");
String scannerpassword = sc.nextLine();
//比对
if (username.equals(scannerusername) & password.equals(scannerpassword)){
System.out.println("登陆成功!");
break;
}
else {
if (i == 3){
System.out.println("机会已经用完,请您明天再试!");
}
System.out.println("输入有误,请重新输入,您还有" + (3 - i) + "次机会");
}
}
}
}
2. 字符串的遍历
- public char[ ] toCharArray(): 将字符串转换为字符数组
public static void main(String[] args) {
String s = "Benjieming";
char[] chs = s.toCharArray();
for (int i = 0; i < chs.length; i++) {
System.out.println(chs[i]);
}
}
- public char chatAt(int index):根据索引找字符
public static void main(String[] args) {
String s = "Benjieming";
for (int i = 0; i < s.length(); i++) {
char a = s.charAt(i);
System.out.println(a);
}
}
- public int length():返回字符串的长度
案例:统计字符次数
需求:键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数,不考虑其他字符。
import java.util.Scanner;
public class TestDemo02 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
//接收输入的字符串
String s = sc.nextLine();
int smallCount = 0;
int bigCount = 0;
int numCount = 0;
//将接收到的字符串转换为字符数组
char[] chars = s.toCharArray();
//统计字符次数
for (int i = 0; i < chars.length; i++) {
if (chars[i] >= 'a' & chars[i] <= 'z'){
smallCount++;
}
else if (chars[i] >= 'A' & chars[i] <= 'Z'){
bigCount++;
}
else if (chars[i] >= '0' & chars[i] <= '9'){
numCount++;
}
}
System.out.println("小写字母为:" + smallCount + "个");
System.out.println("大写字母为:" + bigCount + "个");
System.out.println("数字字母为:" + numCount + "个");
}
}
运行结果为:
请输入字符串:
asc23H4cYG15Ifd
小写字母为:6个
大写字母为:4个
数字字母为:5个
3. 字符串的截取
- public String substring(int beginIndex):根据传入的索引开始做截取,截取到字符串的末尾
public static void main(String[] args) {
String s = "Benjieming";
String result = s.substring(3);
System.out.println(result); //运行结果为jieming
}
- public String substring(int beginIndex, int endIndex):根据传入的开始和结束索引,对字符串做截取
public static void main(String[] args) {
String s = "Benjieming";
String result = s.substring(3,6);
System.out.println(result); //运行结果为jie
}
注意:该方法对于字符串的截取位置包含头,不包含尾。
案例:手机号屏蔽
需求:以字符串的形式从键盘接收一个手机号,将中间四位号码屏蔽。
例如:137****0836
import java.util.Scanner;
public class TestDemo03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的手机号:");
String phoneNumber = sc.nextLine();
//截取手机号前3位
String s1 = phoneNumber.substring(0,3);
//截取手机号后4位
String s2 = phoneNumber.substring(7);
System.out.println(s1 + "****" + s2);
}
}
运行结果为:
请输入您的手机号:
13712345678
137****5678
4. 字符串的替换
- public String replace(旧值, 新值):替换
public static void main(String[] args) {
String s = "Benjieming";
String result = s.replace("jie", "xin");
System.out.println(result); //运行结果为Benxinming
}
注意:返回值才是替换之后的结果。
案例:敏感词替换
需求:键盘录入一个字符串,如果字符串中包含(TMD),则使用 *** 替换。
import java.util.Scanner;
public class TestDemo04 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String result = s.replace("TMD", "***");
System.out.println(result);
}
}
运行结果为:
你TMD是不是有病
你***是不是有病
5. 字符串的切割
- public String[ ] split(String regex):
根据传入的字符串作为规则进行切割,将切割后的内容存入字符串数组中,并将字符串数组返回
public static void main(String[] args) {
String s = "123,45,67,8";
String[] result = s.split(",");
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
运行结果为:
123
45
67
8
注意:先正常指定切割规则,但如果没有得到自己想要的结果,就可以尝试在规则前面加入 \\
例如:
public static void main(String[] args) {
String s = "123.45.67.8";
String[] result = s.split("\\.");
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
运行结果为:
123
45
67
8
五、StringBuilder 类
1、StringBuilder 是一种可变的字符序列。
2、StringBuilder 是字符串的缓冲区,我们可以将其理解为是一种容器,这个容器可以存储任意数据类型,但是只要进入到这个容器中,全部变为字符串。
例如:
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb);//直接打印内容,此时容器中为空
sb.append(10);//向容器中添加数据
System.out.println(sb);
sb.append(10.5);//向容器中添加数据
System.out.println(sb);
sb.append("一二三");//向容器中添加数据
System.out.println(sb);
}
运行结果为:
10
1010.5
1010.5一二三
六、StringBuilder 类的构造方法
1、public StringBuilder ( ):创建一个空的字符串缓冲区(容器)
StringBuilder sb = new StringBuilder();
2、public StringBuilder (String str):创建一个字符串缓冲区,并初始化好指定的参数内容
StringBuilder sb1 = new StringBuilder(10);
StringBuilder sb2 = new StringBuilder("吴彦祖");
七、StringBuilder 类的常用成员方法
1、public StringBuilder append (任意类型):添加数据,并返回对象自己
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append(123).append("wuyanzu").append('a');
System.out.println(sb);
}//运行结果为123wuyanzua
链式编程:如果调用的方法返回的结果是对象,就可以继续向下调用方法。
2、public StringBuilder reverse ( ):将缓冲区中的内容进行反转
3、public int length ( ):返回长度
4、public String toString ( ):将缓冲区中的内容以 String 字符串类型返回
注意:该方法可运用在当数据存在于 StringBuilder 中,但是要用的方法 StringBuilder 中不存在,而 String 中存在需要的方法。
八、案例分析
1. 对称字符串的判断
需求:键盘接收一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是。
思路:对拿到的字符串进行反转,如果反转之后的字符串与反转前的字符串相同,则为对称字符串。
import java.util.Scanner;
/*
String ---> StringBuilder:
String s = "abc";
StringBuilder sb = new StringBuilder(s);
StringBuilder ---> String:
String s = sb.toString();
*/
public class TestDemo01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个对称字符串:");
String s = sc.nextLine();
//将String类型转换为StringBuilder类型,目的是为了调用StringBuilder中的反转方法
StringBuilder sb = new StringBuilder(s);
sb.reverse();
//s为String类型,sb为StringBuilder类型,类型不一致,需要先转换类型
if (s.equals(sb.toString())){
System.out.println("是对称字符串");
}
else {
System.out.println("不是对称字符串");
}
}
}
运行结果为:
请输入一个对称字符串:
123321
是对称字符串
2. 数组中数据转换为字符串
需求:定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回。调用该方法,并在控制台输出结果。
例如:
数组为 int[ ] arr = {1,2,3};
执行方法后的输出结果为:[1, 2, 3]
public class TestDemo02 {
public static void main(String[] args) {
int[] arr = {1,2,3};
String result = arrayToString(arr);
System.out.println(result);
}
public static String arrayToString(int[] arr){
//创建StringBuilder,准备进行拼接
StringBuilder sb = new StringBuilder("[");
//遍历数组,获取内部元素
for (int i = 0; i < arr.length; i++) {
//将获取到的元素拼接到字符串缓冲区
sb.append(arr[i]);
if (i == arr.length - 1) {
sb.append("]");
break;
}
else {
sb.append(", ");
}
}
return sb.toString();
}
}
运行结果为:
[1, 2, 3]