一、字符串:
-
C语言中,字符串用字符数组来实现。
- Java语言中,用类来实现,该类共分为两大类:
- 字符串常量:不可修改的字符串,存放在String类的对象中;
- 字符串变量:可以修改的字符串,存放在StringBuffer类的对象中。
二、String类:
2.1 String类的特征:
1. 字符串常量用String类表示。
2. 对于所有用双引号括起来的字符串常量,系统都会为其创建一个无名的String类型对象 (匿 名对象)。
3. Java不允许对字符串对象进行操作,但是有一个例外,+ 运算符,他可以将两个字符串 连接起来。
2.2 字符串常量池的位置分布:
2.3 创建String类对象:
2.3.1 直接赋值:
Java虚拟机会先在字符串常量池中查找有没有“hello这个字符串对象,如果有,直接将字符串 常量池中这个“hello”的对象地址返回,赋给变量str;如果没有,在字符串常量池中创建“hello”这个对象,然后将其地址返回,赋给变量str。
public class String对象 {
public static void main(String[] args){
String str1 = "hello";
String str2 = "hello";
String str3 = "hello";
System.out.println(str1 == str2); //true
System.out.println(str1 == str3); //true
System.out.println(str2 == str3); //true
//三个输出结果均为true,说明三者地址相同,地址指向的对象也就相同
}
}
2.3.2 用构造方法对对象实例化
当使用new关键字创建对象时,JVM仍然首先检查字符串池中是否存在要创建的字符串,如果不存在,则在字符串池中创建字符串对象,然后在堆内存中继续创建一个字符串对象,返回该对象的引用地址。如果存在,则只在堆内存中创建一个字符串对象,返回该对象的引用地址。
凡使用String类,建议采用第一种方法。因为本身占用内存空间少,而且以后再声明与之一样的字符串的话不会重新开辟新的内存空间。
public class String对象 {
public static void main(String[] args){
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1 == str2); //false
}
}
2.3.3 字符串的" + "运算
public class String对象 {
public static void main(String[] args){
String str1 = "hello";
String str2 = "world!";
String str3 = "hello" + "world!";
String str4 = str1 + str2;
System.out.println(str1 == str3); //false
System.out.println(str2 == str3); //false
System.out.println(str1 == str4); //false
System.out.println(str2 == str4); //false
System.out.println(str3 == str4); //false
}
}
字符串字面量拼接操作是在Java编译器编译期间执行,直接将拼接的这个常量放入字符串池。
字符串引用的+运算是在Java运行期间执行的,会被转为StringBuilder,并且拼接。
String str4=(new StringBuilder0).append(str1).append(str2).toString()字符串连接之后的对象在堆空间,不会自动进入常量池。intern()方法手动将字符串加入常量池中,首先查询常量池中是否有字符串存在,如果存在,则返回常量池中的引用,当字符串常量池中找不到对应的字符串时,而只是生成一个对该字符串的引用在字符串常量池。
public class String对象 {
public static void main(String[] args){
String str1="hello";
String str2=" world!";
String str3 = str1+str2;
str3.intern();
String str4 = "hello world!";
System.out.println(str3==str1); //false
System.out.println(str3==str2); //false
System.out.println(str3==str4); //true
}
}
String str3 = str1 + str2在堆空间中创建对象,str3.intern()先在常量池中寻找有没有“hello world1”这一常量值,发现没有,然后在常量池中创建这一对象,返回这一对象的引用(堆中的地址)。str4发现常量池中有“hello world!”这一常量值,便将其地址赋值给str4,因此str3和str4的地址值相同。
public class String对象 {
public static void main(String[] args){
String str1="hello";
String str2=" world!";
String str3 = str1+str2;
String str4 = "hello world!";
str3.intern();
System.out.println(str3==str1); //false
System.out.println(str3==str2); //false
System.out.println(str3==str4); //false
}
}
str4在常量池中创建“hello world!”这一常量,str3.intern()发现常量池中有“hello world!”这一常量,直接将“hello world!”给返回出去,但是返回值并没有被str3所接受,所以此时str3中的地址仍然为堆中的地址,所以str3==str4输出false,如果是str3 = str3.intern(),那么此时str3==str4输出true。