一、String 概述
-
java.lang.String 类代表字符串,String类定义的变量可以用于指定字符串对象,然后操作该字符串。
-
Java程序中的所有字符串文字(例如:“abc” ; “三国”)都称为此类的对象。
-
语法格式:
String name = "关羽"; String schoolName = "bilibili大学";
二、String类的特点详解
1. 不可变字符串类型
- String其实常常被称为不可变字符串类型,它的对象在创建后不能被更改。
2. 提出问题
- 从上述代码可以看出字符串变量name指向的字符串对象,那为何还说是不可变字符串类型?
3. 解决问题
-
首先要知道字符串对象存在哪里?
- 答:以 “” 方式给出的字符串对象,在字符串常量池中存储 ——> 存在堆内存
-
通过内存题解来解释 字符串类型不可变的原理
-
图1说明:
1.第一步: 会将main方法加载到栈内存中运行 2.第二步: 执行main方法中的第一行程序: String name = "bilibili"; (2.1) 此时,会将 "bilibili" 加载到堆内存中的字符串常量池, 然后将字符串常量池的内存地址 赋值给 变量name,此时的name就会指向 "bilibili"。 解释一下: name中存的其实是字符串常量池的内存地址,只是sum公司做了处理, 输出到控制台的时候,就是根据这个name存的字符串常量池的内存地址去找到对应的 字符串进行输出 ——>这里是继承的内容,后面会讲解到,先知道这个意思。
-
图2说明:
3.第三步: 执行main方法中的第二行程序: name += "教育"; (3.1) 此时,会将 "教育" 加载到堆内存中的字符串常量池,然后把 "bilibili" 和 "教育" 进行运算(字符串拼接),运算后,在堆内存中得到一个新对象: "bilibili教育",此时的name就会指向这个新对象: "bilibili教育"。 解释一下: 此时我们可以看到字符串常量池中是不会改变的, 这就是字符串类型不可变的原因。
-
图3说明:
4.第四步: 执行main方法中的第三行程序: name += "中心"; (4.1) 此时,会将 "中心" 加载到堆内存中的字符串常量池,然后把 "bilibili教育" 和 "中心" 进行运算(字符串拼接),运算后,在堆内存中得到一个新对象: "bilibili教育中心",此时的name就会指向这个新对象: "bilibili教育中心"。 解释一下: 此时我们可以看到字符串常量池中的"bilibili"、"教育"、"中心", 都不会发生改变,这就是 “String常被称为不可变字符串类型,它的对象在创建后 不能被更改” 这句话的原因。 5.第五步: 执行main方法中的第五行程序: System.out.println(name); (5.1) 此时,会根据name指向最新对象: "bilibili教育中心",在控制台显示: bilibili教育中心。
重点总结
1、String是什么?可以做什么?
- 字符串类型,可以定义字符串变量 指向 字符串对象。
2、String是不可变字符串的原因?
- String变量每次的修改其实都是产生并指向了新的字符串对象。
- 原来的字符串对象都是没有改变的,所以称不可变字符串。
三、创建字符串对象的2种方式
1. 第一种方式
-
直接使用 “” 定义。(推荐方式)
String name = "关羽";
2. 第二种方式
-
通过String类的构造器创建对象。
构造器 说明 public String() 创建一个空白字符串对象,不含有任何内容 public String(String original) 根据传入的字符串内容,来创建字符串对象 public String(char[] chs) 根据字符数组的内容,来创建字符串对象 public String(byte[] chs) 根据字节数组的内容,来创建字符串对象
3. 2种方式的示例
package com.app.string;
/**
目标:String类创建字符串对象的2种方式
*/
public class StringDemo2 {
public static void main(String[] args) {
System.out.println("-----------方式一------------");
// 方式1:直接使用双引号创建字符串对象
String name = "关羽揍张飞~~";
System.out.println(name);
System.out.println("-----------方式二------------");
// 方式2:
// 1.public String(): 创建一个空白字符串对象,不含有任何内容(实际开发中几乎不用)
String s1 = new String(); // s1 = ""
System.out.println(s1);
// 2.public String(String): 根据传入的字符串内容,来创建字符串对象(实际开发中几乎不用)
String s2 = new String("刘备真虚伪~~");
System.out.println(s2);
// 3.public String(char[] c): 根据字符数组的内容,来创建字符串对象
char[] chars = {'B', '站', '教', '育', '中', '心'};
// 这个构造器 会遍历 字符数组中的每一个字符,然后拼接成一串字符串
String s3 = new String(chars);
System.out.println(s3); // s3 = "B站教育中心"
// 4.public String(byte[] b): 根据字节数组的内容,来创建字符串对象
byte[] bytes = {97, 98, 99, 65, 66, 67};
// 这个构造器 会遍历 字节数组中的每一个字节,然后转换成一个个字符并拼接成一串字符串
String s4 = new String(bytes);
System.out.println(s4); // s4 = "abcABC"
}
}
控制台:
-----------方式一------------
关羽揍张飞~~
-----------方式二------------
刘备真虚伪~~
B站教育中心
abcABC
Process finished with exit code 0
4. 这2种方式有什么区别(面试常考)
-
以 “” 方式给出的字符串对象,在字符串常量池中存储,而且相同内容只会在其中存储一份。
-
通过构造器 new 对象,每 new 一次都会产生一个新对象,放在堆内存中。
-
示例:
package com.app.string; /** 目标:学会String类创建字符串对象的2种方式,以及理解它们的区别 */ public class StringDemo2 { public static void main(String[] args) { System.out.println("String类创建字符串对象的2种方式"); System.out.println("-----------方式一------------"); // 方式1:直接使用双引号创建字符串对象 String name = "关羽揍张飞~~"; System.out.println(name); System.out.println("-----------方式二------------"); // 方式2: // 1.public String(): 创建一个空白字符串对象,不含有任何内容(实际开发中几乎不用) String s1 = new String(); // s1 = "" System.out.println(s1); // 2.public String(String): 根据传入的字符串内容,来创建字符串对象(实际开发中几乎不用) String s2 = new String("刘备真虚伪~~"); System.out.println(s2); // 3.public String(char[] c): 根据字符数组的内容,来创建字符串对象 char[] chars = {'B', '站', '教', '育', '中', '心'}; // 这个构造器 会遍历 字符数组中的每一个字符,然后拼接成一串字符串 String s3 = new String(chars); System.out.println(s3); // s3 = "B站教育中心" // 4.public String(byte[] b): 根据字节数组的内容,来创建字符串对象 byte[] bytes = {97, 98, 99, 65, 66, 67}; // 这个构造器 会遍历 字节数组中的每一个字节,然后转换成一个个字符并拼接成一串字符串 String s4 = new String(bytes); System.out.println(s4); // s4 = "abcABC" System.out.println("——————————————————————————————————\n"); System.out.println("-------------2种方式的区别----------------"); System.out.println("方式1: "); String str1 = "我是中国人"; String str2 = "我是中国人"; System.out.println("str1是否等于str2: " + (str1 == str2)); System.out.println("\n方式2: "); char[] chars1 = {'a', 'b', 'c'}; String str3 = new String(chars1); String str4 = new String(chars1); System.out.println("str3是否等于str4: " + (str3 == str4)); } }
控制台: String类创建字符串对象的2种方式 -----------方式一------------ 关羽揍张飞~~ -----------方式二------------ 刘备真虚伪~~ B站教育中心 abcABC —————————————————————————————————— -------------2种方式的区别---------------- 方式1: str1是否等于str2: true 方式2: str3是否等于str4: false Process finished with exit code 0
5. 通过 “” 定义字符串的内存原理
6. 通过 new 构造器得到字符串对象的内存原理
重点总结
1、字符串对象的特点有哪些?
- 字符串不可变。
- 双引号创建的字符串对象,在字符串常量池中存储的是同一个。
- 通过 new 构造器创建的字符串对象,在堆内存中是分开存储的。