String类
String类概述
java.lang.String 类代表字符串。Java程序中所有的字符串文字(例如 “abc” )都可以被看作是实现此类的实例。类 String 中包括用于检查各个字符串的方法,比如用于比较字符串,搜索字符串,提取子字符串以及创建具有翻译为大写或小写的所有字符的字符串的副本。
特点:
- 字符串不变:字符串的值在创建后不能被更改。
- 因为String对象是不可变的,所以它们可以被共享。
- 字符串效果上相当于字符数组(char[]),但是底层原理却是字节数组([byte[]])
使用步骤
- 查看类
-java.lang.String :String类位于java.lang包下,凡是位于java.lang包下的类,在使用的时候,不需要导包。 - 查看构造方法
-
String()
初始化新创建的String
对象,使其表示空字符序列。 -
String(char[] value)
分配一个新的String
,以便它表示当前包含在字符数组参数中的字符序列。 -
String(byte[] bytes)
通过使用平台的默认字符集解码指定的字节数组来构造新的String
。 -
String s = “abc” 直接复制的方式创建字符串abc
-
构造举例,代码如下:
// 无参构造
String str = new String();
// 通过字符数组构造
char chars[] = {'a', 'b', 'c'};
String str2 = new String(chars);
// 通过字节数组构造
byte bytes[] = { 97, 98, 99 };
String str3 = new String(bytes);
常用方法
判断功能的方法
boolean | equals(Object anObject) 将此字符串与指定对象进行比较。 |
---|---|
boolean | equalsIgnoreCase(String anotherString) 将此字符串与指定对象进行比较,忽略大小写 |
Object 是” 对象”的意思,也是一种引用类型。作为参数类型,表示任意对象都可以传递到方法中。
练习题
-
需求:模拟完成用户登录
已知用户名和密码,请用程序来实现用户登录,总共有三次机会,登录之后要给出相应的提示。
import java.util.Scanner; public class LoginTest { public static void main(String[] args) { // 假设用户名和密码是已知的 分别为 // String username = "lanqiao"; // String password = "123456"; //用户登录时 用户名和密码有用户从键盘输入 用户最多可尝试三次 for(int i = 0 ; i < 3 ;i++){ // 从键盘录入用户名和密码 Scanner sc = new Scanner(System.in); System.out.println("请输入您的用户名:"); String inName= sc.nextLine(); inName=null; System.out.println("请输入您的密码:"); String inPassword = sc.nextLine(); inPassword=null; //比较用户输入的用户名和密码是否与已知的用户名密码一致 // 当进行字符串和一个变量比较的时候 ,一定要将字符串常量放在equals的前边 这样可以有效的避免空指针异常的出现 if("lanqiao".equals(inName)&&"123456".equals(inPassword)){ System.out.println("登录成功"); break; }else{ if(2 - i == 0){ System.out.println("您的账户已经被锁定,请联系管理员"); }else{ System.out.println("用户名或密码有误,登录失败,您还有"+(2-i)+"次机会!"); } } } } }
遍历字符串
从键盘录入一个字符串,使用程序实现在控制台遍历该字符串。
public static void main(String[] args) {
//从键盘输入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要遍历的字符串:");
String str = sc.nextLine();
// 获取数组的长度 使用数组的length属性 获取字符串的长度 使用的是String类的length方法
for(int i = 0 ; i < str.length();i++){
char c = str.charAt(i);
System.out.println(c);
}
}
-
统计字符的次数
键盘录入一个字符串,统计该字符串中大写字母 小写字母 数字出现的次数 (不考虑其他字符)
对于一个字符判断他是大写字母 小写字母 数字 直接判断:
大写字母: ch >= ‘A’ && ch<=‘Z’
小写字母:ch>=‘a’&& ch<=‘z’
数字:ch>=‘0’&&ch<=‘9’
public class CountCharNum { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入您要统计的字符串:"); String str = sc.nextLine(); // 定义字符统计的变量 int bigCount = 0; int smallCount = 0 ; int numberCount=0; for(int i =0 ; i < str.length();i++){ char ch = str.charAt(i); if(ch >='A'&& ch<='Z'){ bigCount++; }else if(ch >='a'&& ch<='z'){ smallCount++; }else if(ch >='0'&& ch<='9'){ numberCount++; } } System.out.println("大写字母的个数为:" + bigCount); System.out.println("小写字母的个数为:" + smallCount); System.out.println("数字的个数为:" + numberCount); } }
获取功能的方法
boolean | add(E e) 将指定的元素追加到此列表的末尾。 |
---|---|
void | add(int index, E element)` 在此列表中的指定位置插入指定的元素。 |
int | length() 返回此字符串的长度。 |
String | concat(String str) 将指定的字符串连接到该字符串的末尾。 |
char | charAt(int index) 返回 char 指定索引处的值。 |
int | indexOf(String str) 返回指定子字符串第一次出现的字符串内的索引。 |
int | lastIndexOf(int ch) 返回指定字符的最后一次出现的字符串中的索引。 |
String | substring(int beginIndex) 返回一个子字符串,该从beginIndex开始截取字符串到字符 串结尾。 |
String | substring(int beginIndex, int endIndex) 返回一个子字符串,从beginIndex到 endIndex截取字符串。含beginIndex,不含endIndex。 |
static String | valueOf(Object obj) 返回 Object 参数的字符串 Object 形式。 |
boolean | isEmpty() 如果此列表不包含元素,则返回 true |
转换功能的方法
char[] | toCharArray() 将此字符串转换为新的字符数组。 |
---|---|
byte[] | getBytes() 使用平台的默认字符集将此 String 编码为字节序列,将结果存储到新的字节数组中。 |
String | replace(CharSequence target, CharSequence replacement) 将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列 |
CharSequence 是一个接口,也是一种引用类型。作为参数类型,可以把String对象传递到方法中。
分割功能的方法
String[] | split(String regex) 将此字符串按照给定的regex(规则)拆分为字符串数组。 |
---|
public class String_Demo03 {
public static void main(String[] args) {
//创建字符串对象
String s = "aa|bb|cc";
String[] strArray = s.split("|"); // ["aa","bb","cc"]
for(int x = 0; x < strArray.length; x++) {
System.out.println(strArray[x]); // aa bb cc
}
}
}
String的常见陷阱
字符串拼接问题
由于String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象。例如:
public class StringDemo {
public static void main(String[] args) {
String s = "Hello";
s += "World";
System.out.println(s);
}
}
在API中对String类有这样的描述:字符串是常量,它们的值在创建后不能被更改。
根据这句话分析我们的代码,其实总共产生了三个字符串,即"Hello"
、"World"
和"HelloWorld"
。引用变量s首先指向Hello
对象,最终指向拼接出来的新字符串对象,即HelloWord
。
由此可知,如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。为了解决这一问题,可以使用java.lang.StringBuilder
类。
字符串常量存储在字符串常量池中,并且是共享
字符串非常量对象 存储在堆中
String str1 = "abc";
String str2 = new String("abc");
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NGylajNj-1627811344003)(F:\study\笔记\截图\image-20210720170823148.png)]
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "hello" +"world";
String s4 = s1 +"world";
String s5 = s1 + s2;
String s6 = (s1 + s2).intern();
String s7 = "helloworld";
System.out.println(s3==s4);// false
System.out.println(s3 == s7);//true
System.out.println(s3==s5);//false
System.out.println(s4==s5);//false
System.out.println(s3==s6);//true
}
-
常量与常量的拼接,结果在常量池 且常量池中不会存在相同内容的常量
-
只要其中有一个是变量,结果就在堆中。
-
如果拼接的结果调用intern(),结果就在常量池中
public static void main(String[] args) {
String str1 = new StringBuilder("计算机").append("软件开发").toString();
System.out.println(str1.intern()== str1);//true
String str2 = new StringBuilder("ja").append("va").toString();//java是一个特殊的字符串 在jdk的底层,存在很多“java”字符串
System.out.println(str2.intern()==str2);//false
}
面试题:
public static void main(String[] args) {
String str1 = new String("str") + new String("01");
str1.intern();
String str2 = "str01";
System.out.println(str1 == str2);//true
}
public static void main(String[] args) {
String s1 = new String("he") +new String("llo");
String s2 = new String("h") +new String("ello");
String s3 = s1.intern();
String s4 = s2.intern();
System.out.println(s1==s3);//true
System.out.println(s2 == s4);//false
System.out.println(s3 == s4);//true
}
StringBuilder类
StringBuilder概述
查阅java.lang.StringBuilder的API,StringBuilder又称为可变字符序列,它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。
- 特点
- 一个可变的字符序列。
- 但不保证同步
原来StringBuilder是个字符串的缓冲区,即它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。
它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容。StringBuilder会自动维护数组的扩容。原理如下图所示:(默认16字符空间,超过自动扩充)
使用步骤
-
导包
java.lang.StringBuilder java.lang包下的类,在使用的时候,不需要导包。
-
构造方法
StringBuilder() 构造一个没有字符的字符串构建器,初始容量为16个字符。 |
---|
StringBuilder(int capacity) 构造一个没有字符的字符串构建器,由 capacity 参数指定的初始容量。 |
StringBuilder(String str) 构造一个初始化为指定字符串内容的字符串构建器。 |
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder();
System.out.println(sb1); // (空白)
// 使用带参构造
StringBuilder sb2 = new StringBuilder("itcast");
System.out.println(sb2); // itcast
}
}
常用方法
StringBuilder | append(Object obj) 追加 Object 参数的字符串 Object 形式。 |
---|---|
StringBuilder | reverse() 导致该字符序列被序列的相反代替。 |
String | toString() 返回表示此顺序中的数据的字符串。 |
void | trimToSize() 尝试减少用于字符序列的存储。 |
public static void main(String[] args) {
//StringBuilder对象的创建 底层本质依然是字节数组
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder(32);//构建一个容量为32的字节数组
StringBuilder sb3 = new StringBuilder("abcdef");
sb1.append("abc").append(123).append(true);//链式编程
String str = sb1.toString();
System.out.println(str);
System.out.println(sb1.length());
sb1.insert(3,"hello");
System.out.println(sb1.toString());
System.out.println(sb1.reverse().toString());//字符串的反转 逆序
sb1.setCharAt(0,'A');
System.out.println(sb1.toString());// 修改指定位置的字符
}
String和StringBuilder
StringBuilder和String的区别
-
String : 内容是不可变的
-
StringBuilder : 内容是可变的
实现一个将String和Stringbuilder两个对象之间的相互转换
- 将StringBuilder 转换为String
String
toString()
返回表示此顺序中的数据的字符串。
- 将String转换为StringBuilder
StringBuilder(String str)
构造一个初始化为指定字符串内容的字符串构建器。
StringBuilder和String的使用场景
-
如果只是单纯的使用到一个字符串,则直接使用String
-
如果字符串的内容是需要动态改变(动态拼接)则是用Stringbuilder
-
StringBuffer 和Stringbuilder的区别:
Stringbuffer 线程同步的 线程安全的
Stringbuilder线程不同步 线程不安全的
在一般情况下 使用StringBuilder ,在多线程环境下 进行字符串的拼接操作 此时就需要考虑使用StringBuffer
回表示此顺序中的数据的字符串。
- 将String转换为StringBuilder
StringBuilder(String str)
构造一个初始化为指定字符串内容的字符串构建器。
StringBuilder和String的使用场景
-
如果只是单纯的使用到一个字符串,则直接使用String
-
如果字符串的内容是需要动态改变(动态拼接)则是用Stringbuilder
-
StringBuffer 和Stringbuilder的区别:
Stringbuffer 线程同步的 线程安全的
Stringbuilder线程不同步 线程不安全的
在一般情况下 使用StringBuilder ,在多线程环境下 进行字符串的拼接操作 此时就需要考虑使用StringBuffer