Java基础学习-第九章 Java常用类
一、String类别及其常用方法
1. String特点:不可变字符序列(不可变性)
- String类:表示字符串,由一对双引号引起。
- String类
- String存储类对象的字符内容该数组在中间声明final(常量),代表**不可变的字符序列(不可变性):char数组引用类型变量value数组中的元素不能重新赋值,也不能修改**
- 当,需要,不能修改原件char型数组中的元素
- 当,也需要,不能修改原件char型数组中的元素
- 当,也需要,不能修改原件char型数组中的元素
- String类实现了Serializable接口:表示字符串是可序列化的,即String对象可以传输(io流再详细);实现了Comparable接口:表示String对象可以比较大小
/* ******** 体验字符串的不可变性 ******** 注:通过字面量实例化String对象:此时String方法区字符串常量池中存储对象引用类型变量指向的字符串常量 相同内容的字符串常量池中不容的字符串常量 */ public class StringTest {
@Test public void test1() {
//两个String对象的字面量定义相同,因为字符串常量池中不存在相同内容的字符串常量 //因此String对象的引用s1和s2指向方法区字符串常量池中同一个字符串常量,故地址值相同 String s1 = "abc"; ////字面量的定义 String s2 = "abc"; System.out.println(s1 == s2); //true //当对String当对象重新赋值时,需要重新指定内存区域,创建新的char型数组存储新字符串常量, 不能修改原件char型数组中的元素,所以此时String对象的引用s1和s2指向不同的字符串常量,不同的地址值 s1 = "hello"; System.out.println(s1); //hello System.out.println(s2); //abc System.out.println(s1 == s2); //false //当对现有字符串进行连接操作时,需要重新指定内存区域创建一个新的char类数组存储连接后的字符串常量, //而不能修改原有char型数组中的元素,故此时String类型的引用s2和s3指向字符串常量,地址值不同 String s3 = "abc"; s3 = "def";
System.out.println(s3); //abcdef
System.out.println(s2); //abc
System.out.println(s2 == s3); //false
//当调用String类的replace()方法替换String对象的指定字符或字符串时,
//需要重新指定内存区域创建一个新的char型数组存储替换后的字符串常量,不能修改原有char型数组中的元素
String s4 = "abc";
String s5 = s4.replace('a', 'm');
System.out.println(s4); //abc
System.out.println(s5); //mbc
System.out.println(s4 == s5); //false
}
}
2. String类的对象实例化方式
2.1 方式一:通过字面量的方式
- 通过字面量的方式实例化String对象:此时String类型的引用类型变量指向的是方法区字符串常量池中的字符串常量()
- 字符串常量池中不会存在相同内容的字符串常量
String str = "hello";
2.2 方式二:通过new + 构造器的方式
- 通过new + 构造器的方式实例化String对象:此时String类型的引用类型变量指向的是堆空间中new出来的String对象(字符串非常量对象);而堆空间中的String对象又加载了value属性(char型数组的引用类型变量),指向字符串常量池中的字符串常量()
- String类中声明的重载的构造器:
//本质上this.value = new char[0];
String s1 = new String();
//this.value = original.value;
String s2 = new String(String original);
//this.value = Arrays.copyOf(value, value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
2.3 两种String对象实例化方式的区别
2.3.1 例一
public class StringTest {
@Test
public void test2() {
/* 通过字面量的方式实例化String对象:此时引用类型变量s1和s2指向的是方法区字符串常量池中的字符串常量 (一个引用,一个对象,一个地址值) */
String s1 = "javaEE";
String s2 = "javaEE";
/* 通过new + 构造器的方式实例化String对象:此时引用类型变量s3和s4指向的是堆空间中new出来的String 对象(字符串非常量对象);而堆空间中的String对象又加载了value属性(char型数组的引用),指向字符串常 量池中的字符串常量(两个引用,两个对象,两个地址值) */
String s3 = new String("javaEE");
String s4 = new String("javaEE");
//字符串常量池中不会存储相同内容的字符串常量
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false
System.out.println(s1 == s4); //false
System.out.println(s3 == s4); //false
}
}
2.3.2 例二
public class StringTest {
@Test
public void test3() {
Person p1 = new Person("Tom", 12);
Person p2 = new Person("Tom", 12);
//String类重写了equals方法,比较的是两个String对象的实际内容
System.out.println(p1.name.equals(p2.name)); //true
/* == 比较的是两个String类型引用的地址值,这里是字面量定义,由于字符串常量池中不会存储相同内容的字符串 常量,因此二者指向字符串常量池中同一个字符串常量,地址值相同 */
System.out.println(p1.name == p2.name); //true
/* 当对String对象重新赋值时,需要重新指定内存区域创建一个新的char型数组存储新的字符串常量,而不能修改 原有char型数组中的元素,故此时String对象的引用p1.name和p2.name指向不同的字符串常量,地址值不同 */
p1.name = "Jerry";
System.out.println(p2.name); //Tom
}
}
2.3.3 例三
@Test
public void test3() {
String a = "123";
String b = "123";
String c = new String("123");
String d = new String("123");
//String类重写的equals方法比较实际字面量内容
System.out.println(a.equals(b)); //true
//二者都是字面量方式定义,指向方法区字符串常量池中同一个字符串常量(字符串常量池中不会存在相同内容的常量)
System.out.println(a == b); //true
//String类重写的equals方法比较实际字面量内容
System.out.println(c.equals(d)); //true
//二者都是new+构造器的方式定义,指向堆空间中两个不同的对象实体
System.out.println(c == d); //false
//String类重写的equals方法比较实际字面量内容
System.out.println(a.equals(c)); // true
//一个是字面量定义,直接指向字符串常量池中的字符串常量;一个是new+构造器定义,指向堆空间中的对象实体
//而堆空间中的对象又加载了value属性(char型数组的引用类型变量),指向字符串常量池中的字符串常量
System.out.println(a == c); //false
}
2.4 【面试题】new + 构造器的方式实例化String对象,在内存中创建了几个对象?
- 。通过new + 构造器的方式实例化String对象:此时String类型的引用类型变量指向的是==;而堆空间中的String对象又加载了(char型数组的引用类型变量),(==)
2.5 String不同拼接操作的对比
- 与**(字面量)字符串常量**的拼接结果直接存储在字符串常量池,且字符串常量池中不会存在相同内容的字符串常量()
- 在String拼接操作中,基本数据类型变量或引用类型变量),拼接后就**相当于在堆空间中new了一个String对象(字符串非常量对象)**,而堆空间中的String对象又加载了value属性(char型数组的引用类型变量),指向字符串常量池中的字符串常量()
- 如果拼接的结果调用==,方法的返回值,即给引用类型变量赋的值是==
2.5.1 例一
public class StringTest {
@Test
public void test4() {
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
/* (字面量)字符串常量与(字面量)字符串常量的拼接结果直接存储在字符串常量池,且字符串常量池中不会存在相同 内容的字符串常量(一个引用,一个对象,一个地址值) */
String s4 = "javaEE" + "hadoop";
/* 在String拼接操作中,只要其中有一个是变量(基本数据类型变量或引用类型变量),拼接后就相当于在堆空间中 new了一个String对象(字符串非常量对象),而堆空间中的String对象又加载了value属性(char型数组的引 用类型变量),指向字符串常量池中的字符串常量(两个引用,两个对象,两个地址值) */
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
//如果拼接的结果调用intern()方法,方法的返回值,即给引用类型变量赋的值是字符串常量池中的地址值
String s8 = (s1 + s2).intern();
//两个引用的值都是字符串常量池中同一个字符串常量的地址
System.out.println(s3 == s4); //true
//一个引用的值是字符串常量池中的地址,另一个引用的值是堆空间中的地址
System.out.println(s3 == s5); //false
System.out.println(s3 == s6); //false
System.out.println(s3 == s7); //false
//两个引用的值是堆空间中不同对象的地址值
System.out.println(s5 == s6); //false
System.out.println(s5 == s7); //false
System.out.println(s6 == s7); //false
//两个引用的值都是字符串常量池中同一个字符串常量的地址
System.out.println(s3 == s8); //true
}
}
2.5.2 例二
2.5.3 例三
分析下列程序运行的结果:
public class StringTest1 {
String str = new String("good"); //引用str指向堆空间中的String对象
char[] ch = {
't', 'e', 's', 't' };
public void change(String str, char ch[]) {
/* 通过字面量的方式给String对象赋值:需要重新指定内存区域创建一个新的char型数组存储新的字符串常量,而 不能修改原有char型数组中的元素,这里只是让该引用类型的形参指向了方法区字符串常量池中另一个字符串常量 */
str = "test ok"; //String的不可变性
//对于数组对象而言,其引用类型的形参和实参都指向堆空间中同一个数组实体
ch[0] = 'b'; //数组没有不可变性
}
public static void main(String[] args) {
StringTest1 ex = new StringTest1();
ex.change(ex.str, ex.ch);
System.out.println(ex.str); //good:String的不可变性
System.out.println(ex.ch); //best:数组或普通对象没有不可变性
}
}
2.5.4 例四
public void test4() {
String s1 = "javaEEhadoop"; //字面量定义:引用类型变量s1直接指向字符串常量池中的字符串常量
String s2 = "javaEE";
String s3 = s2 + "hadoop"; //字符串常量与变量拼接,引用类型变量s3的值是堆空间中的地址值
System.out.println(s1 == s3); //false
final String s4 = "javaEE"; //s4是一个常量:final
//常量与常量的拼接结果直接存储在字符串常量池,引用类型变量s5的值是字符串常量池中的地址值
String s5 = s4 + "hadoop";
//字符串常量池中不会存在相同内容的字符串常量,故此时s1和s5中保存的是常量池中同一个字符串常量的地址值
System.out.println(s1 == s5); //true
}
3. String类的常用方法
3.1 高频常用
- : 返回字符串(存放字符内容的char型数组)的长度: return value.length
- : 返回某索引处的字符return value[index]
- : 判断是否是空字符串(判断char型数组的长度是否为0): return value.length == 0
- : 使用默认语言环境, 将 String 中的所有字符转换为小写
- : 使用默认语言环境, 将 String 中的所有字符转换为大写
- : 返回字符串的副本, 忽略前导空白和尾部空白
- :比较字符串的实际内容是否相同
- :比较字符串的实际内容是否相同,忽略大小写
- : 将指定字符串连接到此字符串的结尾。 等价于用“+”
- : 比较两个字符串的大小(逐字符比较ASCII码的大小),返回正数表示调用该方法的字符串大,返回负数表示作为形参的字符串大,可用于字符串排序
- :返回当前字符串从beginIndex开始截取到最后的一个字符的子字符串
- :返回当前字符串从beginIndex到endIndex(不包含)的子字符串(左闭右开)
public class StringMethodTest {
@Test
public void test1() {
String s1 = "HelloWorld";
//1. int length(): 返回字符串(存放字符内容的char型数组)的长度: return value.length
System.out.println(s1.length()); //10
//2. char charAt(int index): 返回某索引处的字符return value[index]
System.out.println(s1.charAt(0)); //H
//3. boolean isEmpty(): 判断是否是空字符串(判断char型数组的长度是否为0): return value.length == 0
System.out.println(s1.isEmpty()); //false
//4. String toLowerCase(): 使用默认语言环境,将 String 中的所有字符转换为小写
//5. String toUpperCase(): 使用默认语言环境,将 String 中的所有字符转换为大写
String s2 = s1.toLowerCase();
System.out.println(s1); //HelloWorld:String的不可变性
System.out.println(s2); //helloworld
//6. String trim(): 返回字符串的副本, 忽略前导空白和尾部空白
String s3 = " hello world ";
String s4 = s3.trim();
System.out.println(s3); // hello world :前后都有空格
System.out.println(s4); //hello world:前后没有空格
//7. boolean equals(Object obj): 比较字符串的实际内容是否相同
//8. boolean equalsIgnoreCase(String anotherString): 比较字符串的实际内容是否相同, 忽略大小写
String s5 = "HelloWorld";
String s6 = "helloworld";
System.out.println(s5.equals(s6)); //false
System.out.println(s5.equalsIgnoreCase(s6)); //true
//9. String concat(String str): 将指定字符串连接到此字符串的结尾。 等价于用“+”
System.out.println(s6.concat("fff")); //helloworldfff
System.out.println(s6 + "fff"); //helloworldfff
//10. int compareTo(String anotherString): 比较两个字符串的大小(逐字符比较ASCII码的大小),
//返回正数表示调用该方法的字符串大,返回负数表示作为形参的字符串大,可用于字符串排序
String s7 = "abc";
String s8 = new String("abe");
System.out.println(s7.compareTo(s8)); //-2
//11. String substring(int beginIndex):返回当前字符串从beginIndex开始截取到最后的一个字符的子字符串
//12. String substring(int beginIndex, int endIndex):返回当前字符串从beginIndex到endIndex(不包含)的子字符串
String s9 = "今天天气不错";
System.out.println(s9.substring(2)); //天气不错
System.out.println(s9.substring(2, 4)); //天气
}
}
3.2 查找
- : 测试此字符串是否以指定的后缀结束(没有要求要写几个字符)
- : 测试此字符串是否以指定的前缀开始
- : 测试此字符串从指定索引开始的子字符串是否以指定前缀开始
- : 当且仅当此字符串包含指定的 char 值序列时,返回 true
- : 返回指定子字符串在此字符串中第一次出现处的索引
- : 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始搜索
- : 返回指定子字符串在此字符串中最后一次出现处的索引
- : 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
- 注:和方法如果未找到都返回-1
- 问题:什么情况下,**indexOf(str)lastIndexOf(str)**的返回值相同?
- ① 调用方法的字符串中只有唯一的一个str子字符; ② 未找到都返回-1
public class StringMethodTest { @Test public void test2() { String s1 = "helloworld"; //13. boolean endsWith(String suffix): 测试此字符串是否以指定的后缀结束(没有要求要写几个字符) System.out.println(s1.endsWith("ld")); //true //14. boolean startsWith(String prefix): 测试此字符串是否以指定的前缀开始 System.out.println(s1.startsWith("Hell")); //false //15. boolean startsWith(String prefix, int toffset): 测试此字符串从指定索引开始的子字符串是否以指定前缀开始 System.out.println(s1.startsWith("ll", 2)); //true //16. boolean contains(CharSequence s): 当且仅当此字符串包含指定的 char 值序列时,返回 true String s2 = "wo"; System.out.println(s1.contains(s2)); //true //17. int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引 System.out.println(s1.indexOf("lo")); //3 //18. int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始搜索 System.out.println(s1.indexOf("lo", 1)); //3 System.out.println(s1.indexOf("lo", 4)); //-1 //19. int lastIndexOf(String str):返回指定子字符串在此字符串中最后一次出现处的索引 String s3 = "hororhhh"; System.out.println(s3.lastIndexOf("or")); //3 //20. int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索 标签:
19sb1j电连接器