String类的构造方法的分类
无参构造
参数为字符串
参数为字符数组
参数为字节数组
代码演示
// 比较new方式和直接赋值方式
String str1 = new String("abc");
String str2 = "abc";
System.out.println("str1==str2: " + (str1 == str2));
System.out.println("str1.equals(str2): " + str1.equals(str2));
System.out.println("--------华丽的分割线--------");
// 比较new和new方式
String str3 = new String("aaa");
String str4 = new String("aaa");
System.out.println("str3==str4: " + (str3 == str4));
System.out.println("str3.equals(str4): " + str3.equals(str4));
System.out.println("--------华丽的分割线--------");
// 比较直接赋值方式之间
String str5 = "hugo";
String str6 = "hugo";
System.out.println("str5==str6: " + (str5 == str6));
System.out.println("str5.equals(str6): " + str5.equals(str6));
执行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7MDIwiE4-1634533750717)(C:Users魏文龙AppDataRoamingTyporatypora-user-imagesimage-20211018110007998.png)]
可以推断出new操作每次都会重新在堆内存中开辟空间进行创建,因为==比较的是两个对象的内存地址值,地址值不同说明是两个不同的对象.
而直接赋值的操作是不会重复创建空间进行值的初始化等一些列操作的.
那么,通过直接赋值操作内存中的操作是怎么完成的呢???
实际上内存中存在一个字符串常量池
2 String常量池内存中实际上存在一个单独的区域用来存储字符串,这个区域就是字符串常量池.
3 String类的特点当通过直接赋值的方式进行字符串创建的时候:
1,先去String常量池中查询是否已经有这个值了
2,如果没有就会进行该字符串的创建
3,下次又进行创建就会发现常量池中已经有这个值了,此时就不会再创建了,直接使用就可以了
核心:String类的值创建后就不可以改变了.
比如进行如下的操作
String str = "a"; str += "b"; str += "c"; sout(str);//打印结果肯定是abc
但是这个时候内存中有a,b,ab,c,abc多个字符串存在,这就是字符串在创建后不能改变.
产生的问题:大量的创建字符串对于内存的资源会产生浪费
解决办法:使用StringBuilder或者StringBuffer进行字符串的拼接操作,使用他们不会产生新的字符串,而是在原来的字符串上进行操作.
4 不同版本JDK中String类底层的区别5 常见方法JDK8 String的底层实现是字符数组char[]
JDK8后 String类的底层实现是字节数组byte[]
通过idea的api提示试试就行了
String str = "weiwenlong";
System.out.println("str.isEmpty() = " + str.isEmpty());
System.out.println("str.contains("wei") = " + str.contains("wei"));
System.out.println("str.startsWith("wei") = " + str.startsWith("wei"));
System.out.println("str.endsWith("long") = " + str.endsWith("long"));
//replace():替换,返回的是新的值
String replace = str.replace("weiwenlong", "魏文龙");
System.out.println(replace);
// 大小写转换
String s = str.toLowerCase();
System.out.println(s);
String s1 = str.toUpperCase();
System.out.println(s1);
// 转换为字节数组
byte[] bytes = str.getBytes();
for (byte aByte : bytes) {
System.out.println(aByte);
}
//trim():去掉首尾空格
String str2 = " aaa ";
String trim = str2.trim();
System.out.println("trim = " + trim);
//split(re):字符串切割
String str3 = "aaa bbb ccc";
String[] split = str3.split(" ");
for (String s2 : split) {
System.out.println(s2);
}
6 小练习
1,模拟客户端登录
// 模拟数据库中存储的用户名和密码
String usernameFromDB = "root";
String pwdFromDB = "123123";
// 控制输入次数为3次
for (int i = 1; i <= 3; i++) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String usernameInput = scanner.nextLine();
System.out.println("请输入密码:");
String pwdInput = scanner.nextLine();
// 验证操作
if (usernameInput.equals(usernameFromDB) && pwdInput.equals(pwdFromDB)) {
System.out.println("登录成功");
break;
} else {
if (i == 3) {
System.out.println("傻逼么,自己账号都记不住!!!!");
break;
}
System.out.println("用户名或密码输入错误(还有" + (3 - i) + "次机会),请重新输入:");
}
}
2,遍历指定字符串
// 获取一个字符串
Scanner scanner = new Scanner(System.in);
System.out.print("请输入指定的字符串:");
String s = scanner.nextLine();
// 遍历出该字符串的所有字符
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
System.out.println(c);
}
统计字符出现次数(TODO)
字符串拼接案例(TODO)
字符串反转案例(TODO)
7 StringBuffer和StringBuilder
7.1 构造方法概念:可变的字符序列
StringBuffer和StringBuilder的区别:前者是线程安全的,后者是线程不安全的(效率高)
StringBuffer stringBuffer1 = new StringBuffer();
StringBuffer stringBuffer2 = new StringBuffer("weiwenlong");
System.out.println(stringBuffer1);
System.out.println(stringBuffer2);
7.2 常用方法
StringBuffer stringBuffer = new StringBuffer("weiwenlong");
// 插入操作
StringBuffer newStringBuffer = stringBuffer.append(666);
System.out.println(newStringBuffer);
// 在指定位置插入
StringBuffer insert = newStringBuffer.insert(newStringBuffer.indexOf("g") + 1, "888");
System.out.println("insert = " + insert);
// 反转操作
StringBuffer sb = new StringBuffer("abcdef");
sb = sb.reverse();
System.out.println("sb = " + sb);
7.3 StringBuilder与String类型的相互转换
// String--->StringBuilder--->String String abc = "abc"; StringBuilder stringBuilder = new StringBuilder(abc); String s = stringBuilder.toString();



