视频链接
黑马程序员Java视频教程,一套超哇塞的Java教程,java零基础自学入门必看黑马java教程_哔哩哔哩_bilibili
目录
Scanner录入字符串
String next() 遇见空格或者tap就不继续录入了
String nextLine() 以回车作为录入的结束标记
两者各有弊端
next会录入不完整;nextLine不能在nextInt、nextDouble等方法后面使用
对于目前的学习来说,如果我们的用户输入全是字符串,我们用nextLine();如果输入还有除字符串之外的其他类型,我们用next()
String类
特点
- Java中所有的双引号字符串,都是String这个类的对象
- 字符串内容不可改变,想要更改只能用新的对象做替换
- String字符串可以被共享(StringTable)
字符串常量池:但我们使用双引号创建String对象的时候,会检查常量池中是否有该数据
不存在:创建对象,常量池中创建内存并保存地址
存在:复用
在JDK7版本之前StringTable字符串常量池 在方法区里
JDK7及以后版本StringTable在堆空间里
构造方法
- public String():创建一个空白字符串,里面不含任何内容
- public String(char[] chs):根据传入的字符数组,创建字符串对象
- public String(string original):根据传入的字符串,来创建字符串对象
这三个构造方法都没有直接双引号“abc”用的方便,但其实有区别
构造方法区别
String是Java中唯一可以用双引号直接创建对象的类,特殊!
除了双引号创建,上面三个是常见的构造方法
常见面试题
StringTable
回答:结果是true,因为创建s1对象的时候,在字符串常量池StringTable中也创建了空间保存地址,在创建s2的时候先检查StringTable,里面有“abc”字符串,所以直接复用同一地址。
两种构造方式的内存
回答:s1对象是双引号创建的,创建时在堆内存中的StringTable保存内存地址,(注意:String的value保存方式是字符数组Type[]);
创建s2的时候,先new,在堆内存中开辟自己的一个内存空间,然后创建双引号“abc”对象,在StringTable中查找字符串,发现“abc”就复用地址,将该字符串的副本作为新创建的String对象,(以字符数组的形式)保存在开辟的内存空间中,所以创建s2的时候其实创建了两次String对象
最终的结果肯定是False,s1的内存空间保存在StringTable中,而s2是在堆内存中自己开辟的空间,只不过创建的字符串是StringTable中s1的副本!
String变量与常量拼接
回答:
创建s1和s2以及“c”三个对象,都会在串池中记录地址,然后s3需要对字符串变量和常量“c”进行字符串拼接,会调用StringBuilder类中的append方法,将s2和“c” 拼接成“abc”,但此时“abc”是StringBuilder类型不能直接给s3,所以会调用StringBuilder中的toString方法,在堆内存中创建空间保存String对象“abc”,所以s1和s3的内存地址不一样,输出是False!
s1内存地址在串池当中保存,s3的内存地址是StringBulider调用toString方法之后开辟的新空间中保存
String常量拼接
回答:由于Java具有常量优化机制,在编译成字节码文件的时候,会先对变量运算进行处理,所以这段代码编译出来的字节码文件中s2已经是"abc"了,内存中的保存和第一题一样,s1会保存在串池当中,s2直接复用,所以结果为True
比较方法
- public boolean equals方法(要比较的字符串)
- public boolean equalslgnorecase(要比较的字符串)
完全一样结果才是true,否则为false
忽略大小写的比较(验证码比较字符串常用!)
案例-用户登录
需求分析:明确循环次数三次,使用for循环,判断条件:用户名和密码equals(输入的用户名和密码)都正确,则提示登录成功,前两次失败显示登录失败,三次失败后显示次数已经用完。
package com.yuhan.domain;
import java.util.Scanner;
public class StringDemo2 {
public static void main(String[] args) {
String admin = "zhaosi";
String password = "1974abcd";
checkPassword(admin,password);
}
public static void checkPassword(String admin,String password) {
Scanner sc=new Scanner(System.in);
for (int i = 2; i >=0; i--) {
System.out.println("请输入账号:");
String inputA=sc.nextLine();
System.out.println("请输入密码:");
String inputB=sc.nextLine();
if (admin.equals(inputA) && password.equals(inputB)) {
System.out.println("恭喜您,登录成功!");
return;
}
else
{
if(i==0)
{
System.out.println("对不起您的登录机会已经用完");
return;
}
else
{
System.out.println("对不起,您的账号或密码输入有误,请重新输入,您还有"+i+"次机会");
System.out.println("------------------------------------------------------------");
}
}
}
}
}
注意最后一次如果输错的话提前结束循环,不要打印出来剩余0次机会
遍历方法
public char[]toCharArray()将此字符串转换为一个新的字符数组
返回指定索引处的char 值public char charAt(int index)
如果主方法和建立的方法是平级的,那么我们要加static
String对象.length()————返回int整数值,字符串的长度
案例——统计字符次数
案例分析:三个count值,用toCharArray()生成的字符数组进行遍历,每个字符进行判断,最终输出
package com.yuhan.domain;
import java.util.Scanner;
public class StringDemo3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入您想统计的字符串:");
String s1 = sc.nextLine();
staticString(s1);
}
public static void staticString(String s) {
int xiaoxieCount = 0, daxieCount = 0, numCount = 0;
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] >= 'a' && chars[i] <= 'z') {
xiaoxieCount++;
} else if (chars[i] >= 'A' && chars[i] <= 'Z') {
daxieCount++;
} else if (chars[i] >= '0' && chars[i] <= '9') {
numCount++;
}
}
System.out.println("该字符串中有小写字母:" + xiaoxieCount + "个");
System.out.println("该字符串中有大写字母:" + daxieCount + "个");
System.out.println("该字符串中有数字字母:" + numCount + "个");
}
}
运行结果
截取方法
String类的截取方法
public String substring(int beginIndex): 根据传入的索引开始做截取,截取到字符串的末尾public String substring(int beginIndex,int endIndex): 根据传入的开始和结束索引,对字符串做截取 -包含头,不包含尾
注意截取出来的新字符串要用新的String对象接受,两个截取方案都是有返回值的
案例1——手机号屏蔽
需求分析:将Scanner输入的手机号分为三段并做拼接最终输出,用substring
package com.yuhan.domain;
import java.util.Scanner;
public class StringDemo4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入十一位手机号码:");
String phoneNum = sc.nextLine();
String s1 = phoneNum.substring(0, 3);
String s2 = phoneNum.substring(7);
System.out.println("屏蔽后的手机号码为:" + s1 + "****" + s2);
}
}
替换方法
String类的替换方法:
public String replace(CharSequence target, CharSequence replacement)
参数1 :旧值
参数2 : 新值
案例1——敏感词替换
package com.yuhan.domain;
import java.util.Scanner;
public class StringDemo5 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入您想对策划说的话:");
String str = sc.nextLine();
String result =str.replace("TMD","***");
System.out.println(result);
}
}
切割方法
String类的切割方法:
public String[] split(String regex): 根据传入的字符串作为规则,切割当前字符串
在切割的时候.代表任意字符,不能直接作为制定规则,使用的时候要用\\.
使用split的时候先正常使用规则,如果不对就加两个斜线
方法小结
public boolean equals方法(要比较的字符串)比较内容:
public boolean equalsIgnorecase(要比较的字符串):比较内容,忽略大小写
public char[] toCharArray()将字符串转换为字符数组
public char chatAt(int index)根据索引找字符
public int length():返回字符串的长度
public string substring(int beginIndex)截取到末尾public string substring(int beginIndex, int endIndex)根据开始和结束索引做截取,包含头不包含尾
public string replace(旧值,新值)替换
public string[] split(string regex):切割
StringBuilder
可以提高字符串的操作效率
介绍:
1.一个可变的字符序列
2.StringBuilder是字符串缓冲区,将其理解是容器,这个容器可以存储任意数据类型,但是只要进入到这个容器,全部变成字符串。
构造方法
public StringBuilder() 创建一个空的字符串缓冲区(容器)
public StringBuilder(String str) 创建一个字符串缓冲区,并初始化好指定的参数内容
四个方法
1.public StringBuilder append(任意类型):添加数据,并返回对象自己
2.public stringBuilder reverse():将缓冲区中的内容,进行反转
3.public int length():返回长度
4.public String toString():将缓冲区的内容,以String字符串类型返回
public class StringBuilderDemo2 {
public static void main(String[] args) {
StringBuilder sb= new StringBuilder();
sb.append("Hello").append("World").append("!");
System.out.println(sb);
}
}
这里面采用了链式编程思想,append返回的是对象,就可以继续向下调用方法,String中的subString也是一样。
反转同上,因为返回的是对象,所以可以重复调用
toString适用于的情况:数据在StringBuilder中,但是我要调用String的方法,所以要用toString转换为String类型再处理数据
案例1——检查对称字符串
分析:对称字符串的反转一模一样,输入的String先变成StringBuilder用翻转方法,再用toString方法变成字符串对象,才能用equals和输入的字符串进行比较
package com.yuhan.StringBuilder;
import java.util.Scanner;
public class StringBuilderDemo2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要判断的字符串:");
String str = sc.nextLine();
StringBuilder sb1 = new StringBuilder(str);
String result = sb1.reverse().toString();
System.out.println("该字符串是否为对称字符串:" + str.equals(result));
}
}
案例2——输出数组元素
分析:建立StringBuilder,循环遍历数组进行append,注意字符串格式,最终toString接收并输出
package com.yuhan.StringBuilder;
public class StringBuilderDemo3 {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
String result = changeStr(arr);
System.out.println(result);
}
public static String changeStr(int[] arr) {
StringBuilder sb = new StringBuilder("[");
sb.append(arr[0]);
for (int i = 1; i < arr.length; i++) {
sb.append(", ").append(arr[i]);
}
sb.append("]");
return sb.toString();
}
}
[1, 2, 3, 4, 5]
进程已结束,退出代码为 0
为什么StringBuilder的效率高
字符串拼接的时候,需要在堆内存中先创建一个StringBuilder对象再toString创建String对象
所以频繁运用字符串拼接的时候,优先用StringBuilder
StringBuffer
构造方法和使用方法和Builder一样,只不过StringBuffer针对多线程任务是安全的,效率偏低;StringBuilder针对多线程任务是相对不安全的,效率高。