目录
String的概述
Java.lang.String类表示字符串,java程序中的所有字符串文字(例如:“abc”)都为此类对象
注意点 : 字符串的内容是不会发生改变的,它的对象在创建后不能被更改
字符串拼接产生一个新的字符串
三个字符串
两个字符串(下面这种情况并不是改变了原来字符串内容,而是创建了一个新的字符串,把新的字符串再赋值给了name)
创建String对象的两种方式
1.直接赋值
2.通过new关键字,构造不同的方法
//1.使用直接赋值的方法获取一个字符串
String s1 = "abc";
System.out.println(s1);//abc
//2.使用new的方式来获取一个字符串对象
//空参构造:可以获取一个空白的字符串对象
String s2 = new String();
System.out.println(s2);//""
//传递一个字符串,根据传递的字符串内容再创建一个新的字符串对象
String s3 = new String("abc");
System.out.println(s3);//abc
//传递一个字符数组,根据字符数组的内容再创建一个新的字符串对象
//需求:需要修改字符串内容
//abc --> {'a', 'b', 'c'} --> {'Q', 'b', 'c'} --> "qbc"
char[] chs = {'a', 'b', 'c', 'd'};
String s4 = new String(chs);
System.out.println(s4);//abcd
//传递一个字节数组,根据字节数组的内容再创建一个新的字符串对象
//应用场景: 以后在网络当中传输的数据其实都是字节信息
//我们一般要把字节信息进行转换,转成字符串,就要用到这个构造了
byte[] bytes = {97, 98, 99,100};
String s5 = new String(bytes);
System.out.println(s5);//abcd
串池(字符串常量池):只有直接赋值的方式获取字符串对象存在串池中,通过new关键字获取的字符串对象,在JDK7以前,这个池子在方法区里面,在JDK7之后,StringTable串池挪到了堆内存,运行机制不发生变化;
当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在
不存在: 创建新的 存在:复用
手动new出来的,以字符数组为例
每new一次就是开辟了一块新的小空间
那么s1 s2记录的地址值是不一样的,所以这种形式的字符串不会复用,因此相同的字符串比较多,会浪费空间
所以说还是使用第一种直接赋值的方式,代码简单,节约内存
字符串的比较
基本数据类型比较的是数据值,引用数据类型比较的是地址值
有比较内容用下面方法:
boolean equals方法(要比较的字符串) 完全一样结果是true,否则为false
boolean equalsIgnoreCase(要比较的字符串) 忽略大小写的比较(只能是英文状态下)
键盘录入的”abc“ 与在代码中定义的字符串”abc“不一样
String = str1 = sc.next(); 是new出来的;
应用:金额转换
import java.util.Scanner;
public class Test9 {
public static void main(String[] args) {
//1.键盘录入一个金额
Scanner sc = new Scanner(System.in);
int money;
while (true) {
System.out.println("请录入一个金额");
money = sc.nextInt();
if (money >= 0 && money <= 9999999) {
break;
} else {
System.out.println("金额无效");
}
}
//定义一个变量用来表示钱的大写
StringBuilder moneyStr = new StringBuilder();
//2.得到money里面的每一位数字,再转成中文
while (true) {//2135
//从右往左获取数据,因为右侧是数据的个位
int ge = money % 10;
String capitalNumber = getCapitalNumber(ge);
//把转换之后的大写拼接到moneyStr当中
moneyStr.insert(0, capitalNumber);
//第一次循环 : "伍" + "" = "伍"
//第二次循环 : "叁" + "伍" = "叁伍"
//去掉刚刚获取的数据
money = money / 10;
//如果数字上的每一位全部获取到了,那么money记录的就是0,此时循环结束
if (money == 0) {
break;
}
}
//3.在前面补0,补齐7位
int count = 7 - moneyStr.length();
for (int i = 0; i < count; i++) {
moneyStr.insert(0, "零");
}
System.out.println(moneyStr);//零零零贰壹叁伍
//4.插入单位
//定义一个数组表示单位
String[] arr = {"佰","拾","万","仟","佰","拾","元"};
// 零 零 零 贰 壹 叁 伍
//遍历moneyStr,依次得到 零 零 零 贰 壹 叁 伍
//然后把arr的单位插入进去
StringBuilder result = new StringBuilder();
for (int i = 0; i < moneyStr.length(); i++) {
char c = moneyStr.charAt(i);
//把大写数字和单位拼接到result当中
result.append(c).append(arr[i]);
}
//5.打印最终结果
System.out.println(result);
}
//定义一个方法把数字变成大写的中文
//1 -- 壹
public static String getCapitalNumber(int number) {
//定义数组,让数字跟大写的中文产生一个对应关系
String[] arr = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
//返回结果
return arr[number];
}
}
StringBuilder概述
StringBuilder可以看成一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率
String s = s1 + s2 + s3 + s4 + s5 + s6;像这样的拼接它每拼接一次产生一个新的字符串,因此很影响内存,程序的运行效率
StringBuilder是Java已经写好的类,Java底层对它进行了一些特殊处理,打印对象不是地址值而是属性值
StringJoiner概述
Stringjoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。
作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。
JDK8出现的
拼接原理
拼接的时候没有变量,都是字符串,触发字符串优化机制,在编译的时候就已经是最终结果了
-
加号(+)拼接:
-
在早期的Java版本中,使用加号进行字符串拼接时,会创建多个临时的StringBuilder对象,然后进行拼接操作。这是因为字符串是不可变(immutable)的,每次拼接都会创建一个新的字符串对象。这种方式在循环或大量拼接的场景下效率较低
-
-
String的concat方法:
-
String类提供了一个concat方法,用于字符串的拼接。该方法内部使用了StringBuilder来进行字符串的拼接,并返回一个新的字符串对象。
-
-
StringBuilder和StringBuffer:
-
StringBuilder和StringBuffer类是Java提供的可变字符串类,它们在底层使用字符数组(char[])来存储字符串内容。区别在于StringBuilder是非线程安全的,而StringBuffer是线程安全的。
-
使用StringBuilder进行字符串拼接时,会直接对字符数组进行操作,而不会创建多个临时对象。这种方式在性能上比直接使用加号进行拼接要高效得多。
-
StringBuilder通过预先指定容量(capacity)来减少数组扩容的次数,以提高效率。
-
当调用StringBuilder的toString方法时,会将字符数组转换为一个新的String对象。
-
下面是使用StringBuilder进行字符串拼接的示意图:
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString();
-
创建一个空的StringBuilder对象,内部维护一个初始容量为16的字符数组。
-
调用append方法将字符串"Hello"添加到StringBuilder的字符数组中。
-
调用append方法将字符串" "添加到字符数组中。
-
调用append方法将字符串"World"添加到字符数组中。
-
调用toString方法将字符数组转换为一个新的String对象,结果为"Hello World"。
通过使用StringBuilder,可以避免多次创建临时对象,提高字符串拼接的效率。
StringBuilder源码分析的简要概述:
-
StringBuilder类位于
java.lang.StringBuilder
包中。它是一个final类,不能被继承。 -
StringBuilder类实现了
CharSequence
接口,它提供了一系列方法用于进行字符串的操作,如append、insert、delete、replace等。 -
StringBuilder类内部使用一个可变的字符数组(char[])来存储字符串内容,并通过一个整型变量(count)来记录实际存储的字符数。
-
在进行字符串的拼接操作时,StringBuilder会根据需要自动扩容字符数组的大小,以容纳更多的字符。(默认容量:16,扩容 : 老容量 * 2 + 2 ,如果超过老容量 * 2 + 2的容量则以实际容量为准)
-
StringBuilder类中的方法都采用了链式调用的方式,返回的是StringBuilder对象本身,这样可以方便地进行连续的操作。
println
在Java中,println方法用于将数据打印到控制台,并在最后自动换行。当我们使用println方法打印非字符串类型的数据时,需要使用加号(+)将数据和空字符串(" ")连接起来,如System.out.println(data + " ");。
这是因为println方法的参数类型是字符串(String)。当我们传递非字符串类型的数据给println方法时,Java会自动将这些数据转换为字符串类型。这个转换过程涉及到Java的重载(Overloading)机制和字符串拼接(String Concatenation)操作。
底层原理如下:重载机制:Java中的重载允许方法具有相同的名字,但参数列表不同的情况下,通过参数列表的不同来区分不同的方法。对于println方法,存在多个重载版本,可以接受不同类型的参数。
字符串拼接:加号(+)在Java中既可以表示加法运算,也可以表示字符串拼接操作。当加号的操作数中至少有一个是字符串类型时,Java会将加号解释为字符串拼接,而不是数值相加。因此,当我们使用println方法打印非字符串类型的数据时,需要通过加号将数据转换为字符串类型。连接的空字符串(" ")起到了一个辅助作用,可以确保数据转换为字符串后,输出结果之间有一个空格的分隔。
示例代码:
int num = 10;
System.out.println("The number is: " + num + " "); // 输出结果为 "The number is: 10 "在上述代码中,num是一个整数类型的变量。通过将num与空字符串连接,Java将num转换为字符串类型,然后进行字符串拼接操作,最终输出的结果是"The number is: 10 "。
需要注意的是,这种字符串拼接方法在打印大量数据时效率较低,因为每次拼接字符串都会创建一个新的字符串对象。在实际开发中,可以使用更高效的方式,如使用StringBuilder类进行字符串的拼接。