一、String字符串及其拼接:
1.基本概念:
在 Java 中,String
是一个不可变的类,用于表示和操作文本。字符串常量池通过维护字符串字面量的唯一实例,帮助减少内存使用和提高性能。
2.字符串的存储:
2.1.存储位置:
位于堆内存中的字符串常量池中,专门用于存储字符串字面量。
2.2.存储过程:
每当创建一个新的字符串字面量时,JVM 会先检查池中是否已存在相同的字符串。如果存在,则直接使用池中的实例;如果不存在,则将新的字符串添加到池中。
例:
public static void main(String[] args){
String a = "123";//创建字符串
String b = "123";
System.out.println(a==b);
}
内存图:
执行步骤:
-
编译和加载:
javac
编译.java
文件为.class
文件。java
启动 JVM 并将.class
文件加载到方法区。
-
执行
main
方法:main
方法在栈内存中分配空间,创建局部变量a
和b
。
-
字符串常量池:
"123"
作为字符串常量存储在字符串常量池中。a
和b
都引用同一个常量池中的"123"
对象,因此它们指向相同的内存位置(例如0x1
)。
最终,a == b
将输出 true
,因为 a
和 b
引用的是同一个字符串常量池中的实例。
3.String字符串常用操作和方法:
1.length():获取字符串长度
String a = "Hello World";
int q= a.length();
System.out.println(q);
//运行结果:
//11
2.chartAt(index):根据位置获取指定的字符
String aString = "123456";
String bString = new String("123456");
char a = aString.charAt(0);
System.out.println(a);
3.subString(index): 截取字符串
String aString = "123456";
String bString = new String("123456");
System.out.println(aString.substring(3));
System.out.println(aString.substring(3,4));
4.contains(子串):判断是否有子串
if(s1.contains("sd")){
System.out.println("包含sd子串");
}else{
System.out.println("不包含sd子串");
}
5.replace(char oldchar,char newchar) :子串替换
public static void main(String[] args) {
String a = "Hello World";
String b = a.replace("World","end");
System.out.println(b);
}
6.replace(String oldchar,String newchar):子串替换
public static void main(String[] args) {
String a = "Hello World";
String b = a.replace('o','b');
System.out.println(b);
}
4.字符串的拼接:
1.java文件通过javac命令进行编译成.class文件 通过java命令将文件加载到方法区
2. + 运算符进行字符串拼接,在编译完成后拼接,则新的变量是一个新的字符串对象,即使与原来的值相同,在栈中的地址也不同
例:
public static void main(String[] args){
String a = "123" + "456";
String b = "123456";
System.out.println(a==b);
String s1= "123";
String s2 = "456";
String s3 = s1 + s2;
System.out.println(s3);
System.out.println(s3 == b);
}
//true
//123456
//false
- String s1 = "123"; 和 String s2 = "456"; 都是编译时常量,它们指向常量池中的对象。
- String s3 = s1 + s2; 是运行时拼接,因为是在运行时拼接的,因此s3是一个新的字符串对象。即使它的内容是 123456,它的引用不会指向常量池中的 123456 对象。
- s3 是通过 + 运算符拼接的,它不会被存储在常量池中,地址与b不同。
二、new关键字:
如果使用 new 关键字创建字符串(例如 String c = new String("123");),即使常量池中已经有 "123",也会在堆上创建一个新的字符串对象,并不会放入常量池中。
public static void main(String[] args){
String a = "123";
String b = "123";
String c = new String("123");
System.out.println(a==b);
System.out.println(a==c);
}
//==:对基本数据类型是判断值是否相同;引用数据类型比较的是引用地址是否相同
//String 属于类
由此引申出:==和equals的区别
==和equals的区别:
1.比较目的不同:
==用于比较两个引用变量是否指向同一个对象,即它们是否具有相同的内存地址。equals 方法首先判断地址是否相同,如果相等返回true,如果不相等比较的是值是否相等。
2.适用类型的不同:
==可以用于任何类型的比较,包括基本数据类型(如 int、char)和引用数据类型(如对象)。equals 是 Object 类中的方法,所有 Java 对象都继承了这个方法
注意:基本数据类型只能用==来进行判断,对引用数据来讲,==比较的是地址是否相同;对基本数据类型,==进行的是值的判断