String概述(掌握)
基本介绍
基本介绍
-
一个字符串是由多个字符组成的一串数据(字符序列,字符数组)
-
String类代表字符串,Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现
-
在java.lang包下,是java核心类,最常用类,但是不属于基本数据类型
-
String类提供了字符串表示、比较、查找、截取、大小写转换等各种针对字符串的操作
构造方法
//空字符串 ""
public String()
//利用字节数组,创建字节数组所表示的字符串
// 1. 字符 -> 数值形式 'a' -> 97
// 2. 所以可以用多个字节值,表示多个字符——>即字符序列 public
String(byte[] bytes)
//利用字节数数组的一部分,创建字符序列, 从byte数组的offset开始的length个字节值
public String(byte[] bytes,int offset,int length)
//利用一个字符数组创建字符数组,代表的字符序列
public String(char[] value)
// 创建value字符数组中,从第offset位置开始的count个字符,所代表的字符串对象
public String(char[] value,int offset,int count)
//知道即可
public String(String original)
Demo
@Test
public void myTest(){
// //空字符串 ""
// public String()
String s1 = new String();
System.out.println(s1);
System.out.println("123");
// //利用字节数组,创建字节数组所表示的字符串
// // 1. 字符 -> 数值形式 'a' -> 97
// // 2. 所以可以用多个字节值,表示多个字符——>即字符序列 public
// String(byte[] bytes)
byte[] bytes = {97, 98, 99};
String s2 = new String(bytes);
System.out.println(s2);
// //利用字节数数组的一部分,创建字符序列, 从byte数组的offset开始的length个字节值
// public String(byte[] bytes,int offset,int length)
String s3 = new String(bytes, 0, 2);
System.out.println("s3 = " + s3);
// //利用一个字符数组创建字符数组,代表的字符序列
// public String(char[] value)
char[] chars = {'h', 'e', 'l', 'l', 'o'};
String s4 = new String(chars);
System.out.println("s4 = " + s4);
// // 创建value字符数组中,从第offset位置开始的count个字符,所代表的字符串对象
// public String(char[] value,int offset,int count)
String s5 = new String(chars, 0, 3);
System.out.println("s5 = " + s5);
// //知道即可
// public String(String original)
String s6 = new String("aaa");
System.out.println("s6 = " + s6);
}
String特点(重点)
String对象不可变
什么是对象不可变
什么是String对象不可变?
对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。
从对象的角度来看,某个String对象创建完成后,就不能再改变该对象的状态,这就是所谓的对象不可变
- 对象的状态不改变指的是对象中成员变量不能改变,这包括
- 基本数据类型成员变量的取值不能改变
- 引用数据类型成员变量的引用不能指向新的对象
- 引用数据类型成员变量的引用,所指向的对象的状态也不可改变
例子
1.请键盘录入一个任意字符串s,并用一个temp字符串引用也指向它
这个时候修改temp字符串的内容,请问s字符串的内容会随之改变吗?
/*
* 1.请键盘录入一个任意字符串s,并用一个temp字符串引用也指向它
这个时候修改temp字符串的内容,请问s字符串的内容会随之改变吗?
* 创建日期:2022/1/13 10:08
* @return void
* @author 景天
*/
@Test
public void myTest1(){
// 创建Scanner对象
Scanner scanner = new Scanner(System.in);
// nextLine方法 接收键盘数据 s
String s = scanner.nextLine();
System.out.println(s);
// temp 指向
String temp = s;
System.out.println("temp = " + temp);
// 修改temp字符串内容
temp = "aaa";
// 输出
System.out.println("temp = " + temp);
System.out.println("s = " + s);
}
注意
- 并不是把原来的"abc"更改成"aaa",而是新创建了1个对象
- 修改的知识temp指向
例子
String s = "张三";
System.out.println("s = " + s);
s = "hello 张三";
System.out.println("s = " + s);
输出结果是多少?原因是什么?
输出
张三
hello 张三
原因与本质
- String是一个final类,代表不可变的字符序列
- 字符串是常量,用双引号引起来,他们的值在创建之后不可更改
- String对象的内容是存储在字符数组value[ ]中的
字符串常量池
引例:
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
输出结果,原因是什么?
true
false
什么是字符串常量池
字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串使用的非常多
JVM为了提高性能和减少内存的开销,在实例化字符串对象的时候进行了一些优化:
使用字符串常量池。
首先要明确,Java的双引号引起来的字面值常量字符串,它们都是对象。这些对象比较特殊,程序在编译时期就能确定它们的值,编译时期就能作为对象加入“静态常量池”,在类加载时期就能够读取进字符串常量池
每当创建字符串常量对象时,JVM会首先检查字符串常量池,如果该字符串对象已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串对象不存在于常量池中,就会实例化该字符串并且将其放到常量池中。
String两种实例化方式的区别
两种方式
- 直接赋值 String s = “abc”
- 构造方法 String s= new String(“abc”)
区别
- 方式一只创建了1个对象,在常量池中
- 方式二创建了2个对象,1个通过new在堆上,另一个在常量池中
常见练习与问题
字符串内容比较
boolean | equals(Object anObject) 将此字符串与指定的对象比较。 |
---|---|
将此字符串与指定的对象比较。当且仅当该参数不为 null,并且是与此对象表示相同字符序列的 String 对象时,结果才为 true。 |
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2));// true
String s3 = new String("hello");
String s4 = "hello";
System.out.println(s3 == s4); //false
System.out.println(s3.equals(s4)); // true
String s5 = "hello";
String s6 = "hello";
System.out.println(s5 == s6); // true
System.out.println(s5.equals(s6)); // true
==与equals方法有什么区别?
- == ,对于基本数据类型而言,比较的是内容,对于引用数据类型而言,比较的是引用变量,即所指向的地址
- String中重写的equals方法
- equals方法是Object的方法,默认是比较2个对象的地址,若要比较内容,应当重写父类方法
String中重写的equals方法
字符串拼接
String s = "hello";
S+="world";
sout(s)
String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo"; // 等价于 String s3 = "Hello";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s7 = "H";
String s8 = "ello";
String s9 = s7 + s8;
System.out.println(s1 == s2);// true
System.out.println(s1 == s3);//
System.out.println(s1 == s4);
System.out.println(s1 == s9);
System.out.println(s4 == s5);
- 进行字符串拼接的时候有2种情况
- 直接在常量池中创建新的拼接对象
- 在堆上创建新的拼接对象
- 当参与字符串拼接对的2个字符串,只要有1个引用变量的形式出现时,则会在堆上创建新的字符串对象.
- 原因是因为参与了运算,无法在编译期确定其值,就不能在编译时期加入常量池
- 只有参与字符串拼接的2个字符串都是字面值常量的时候,则会在常量池创建拼接对象
- 如果常量池中已有,则不会创建
String API(掌握)
判断功能
用来比较字符串的内容,注意区分大小写
boolean equals(Object obj)
忽略字符串大小写比较字符串内容,常见用于比较网址URL
boolean equalsIgnoreCase(String str)
判断当前字符串对象是否包含,目标字符串的字符序列
boolean contains(String str)
判断当前字符串对象,是否已目标字符串的字符序列开头
boolean startsWith(String str)
判断当前字符串,是否以目标字符串对象的字符序列结尾,常用于确定文件后缀名格式
boolean endsWith(String str)
判断一个字符串,是不是空字符串
boolean isEmpty()
Demo
/*
* 判断功能
* 创建日期:2022/1/13 11:29
* @return void
* @author 景天
*/
@Test
public void myTest1(){
// 用来比较字符串的内容,注意区分大小写
//boolean equals(Object obj)
//忽略字符串大小写比较字符串内容,常见用于比较网址URL
//boolean equalsIgnoreCase(String str)
String s1 = "abc";
String s2 = "ABc";
System.out.println("s1.equalsIgnoreCase(s2) = " + s1.equalsIgnoreCase(s2));
//判断当前字符串对象是否包含,目标字符串的字符序列
//boolean contains(String str)
System.out.println("s1.contains(\"ab\") = " + s1.contains("ab"));
//判断当前字符串对象,是否已目标字符串的字符序列开头
//boolean startsWith(String str)
System.out.println("s1.startsWith(\"ab\") = " + s1.startsWith("ab"));
System.out.println("s1.startsWith(\"de\") = " + s1.startsWith("de"));
//判断当前字符串,是否以目标字符串对象的字符序列结尾,常用于确定文件后缀名格式
//boolean endsWith(String str)
System.out.println(s1.endsWith("bc"));
//判断一个字符串,是不是空字符串 指的不是null 指的是""
//boolean isEmpty()
System.out.println("s1.isEmpty() = " + s1.isEmpty());
System.out.println("\"\".isEmpty() = " + "".isEmpty());
}
获取功能
获取当前字符串对象中,包含的字符个数
int length()
获取字符串对象代表字符序列中,指定位置的字符
char charAt(int index)
在当前字符串对象中查找指定的字符,如果找到就返回字符,首次出现的位置,如果没找到返回-1
也可以填字符
int indexOf(int ch)
指定从当前字符串对象的指定位置开始,查找首次出现的指定字符的位置,(如果没找到返回-1)
可以填入字符
int indexOf(int ch,int fromIndex)
查找当前字符串中,目标字符串首次出现的位置(如果包含),找不到,返回-1
这里的位置是指目标字符串的第一个字符,在当前字符串对象中的位置
int indexOf(String str)
指定,从当前字符串对象的指定位置开始,查找首次出现的指定字符串的位置(如果没找到返回-1)
这里的位置是指目标字符串的第一个字符,在当前字符串对象中的位置
int indexOf(String str,int fromIndex) ,
返回字符串,该字符串只包含当前字符串中,从指定位置开始(包含指定位置字符)到结束的那部分字符串
String substring(int start)
返回字符串,只包含当前字符串中,从start位置开始(包含),到end(不包含)指定的位置的字符串
String substring(int start,int end)
Demo
/*
* 获取功能
* 创建日期:2022/1/13 11:37
* @return void
* @author 景天
*/
@Test
public void myTest2() {
String s = "abcde";
// 获取当前字符串对象中,包含的字符个数
//int length()
System.out.println("s.length() = " + s.length());
//获取字符串对象代表字符序列中,指定位置的字符
//char charAt(int index)
char c = s.charAt(0);
System.out.println(c);
//在当前字符串对象中查找指定的字符,如果找到就返回字符,首次出现的位置,如果没找到返回-1
//也可以填字符
//int indexOf(int ch) 从0开始算
int index = s.indexOf(100);
System.out.println(index);
//指定从当前字符串对象的指定位置开始,查找首次出现的指定字符的位置,(如果没找到返回-1)
//可以填入字符
//int indexOf(int ch,int fromIndex)
int index1 = s.indexOf(99, 1);
System.out.println("index1 = " + index1);
//查找当前字符串中,目标字符串首次出现的位置(如果包含),找不到,返回-1
//这里的位置是指目标字符串的第一个字符,在当前字符串对象中的位置
//int indexOf(String str)
int index2 = s.indexOf("de");
System.out.println(index2);
//指定,从当前字符串对象的指定位置开始,查找首次出现的指定字符串的位置(如果没找到返回-1)
//这里的位置是指目标字符串的第一个字符,在当前字符串对象中的位置
//int indexOf(String str,int fromIndex) ,
//返回字符串,该字符串只包含当前字符串中,从指定位置开始(包含指定位置字符)到结束的那部分字符串
//String substring(int start)
String substring = s.substring(3);
System.out.println("substring = " + substring);
//返回字符串,只包含当前字符串中,从start位置开始(包含),到end(不包含)指定的位置的字符串
// [ )
//String substring(int start,int end)
String substring1 = s.substring(2, 3);
System.out.println("substring1 = " + substring1);
}
课堂练习:
1:遍历获取字符串中的每一个字符
2:统计一个字符串中大写字母字符,小写字母字符,数字字符出现的次数。(不考虑其他字符)
/*
*课堂练习:
1:遍历获取字符串中的每一个字符
2:统计一个字符串中大写字母字符,小写字母字符,数字字符出现的次数。(不考虑其他字符)
* 创建日期:2022/1/13 11:46
* @return void
* @author 景天
*/
@Test
public void myTest3(){
String s = "abc00123AFg";
// 定义3个计数器
// 统计大写的
int countUpper = 0;
// 统计小写的
int countLower = 0;
// 统计数字的
int countDigital = 0;
// 遍历该字符串
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 做判断 计数器的值相应的+1
if (c >= 'A' && c <= 'Z') {
countUpper += 1;
} else if (c >= 'a' && c <= 'z') {
countLower += 1;
}else {
countDigital += 1;
}
// 输出
}
System.out.println("countUpper = " + countUpper);
System.out.println("countLower = " + countLower);
System.out.println("countDigital = " + countDigital);
}