常量池的作用:
在Java中只要是new的信息都会在堆上开辟一个新的空间,为了解决这个问题,JVM中才出现了字符串常量池的概念。但是只有直接用 ""修饰的字符,才会被加入到常量池中,当再次用 ""创建的时候,会首先从常量池中去获取。
字符串常量池存在于运行时常量池中。也就存在于方法区中。(此处关于字符串常量池存放位置,这个是根据jdk版本不同而不同的,此处举例在方法区中。)
<1、String类代表字符串。 Java 程序中的所有字符串面值(如 “abc” )都作 为此类的实例现。
<2、String String是一个 final类,代表不可变的字符序列 。
❤️、字符串是常量 ,用双引号起来表示。 它们的值在创建之后不能更改 。
<4、String 对象的字符 内容是存储在一个字符数组 value[] 中的
实例1:
public class Test{
public static void main(String[] args){
String str ="abc";
String str1 = new String("abc");
String str2 = "abc";
System.out.println(str == str1); //false
System.out.println(str == str2); //true
}
}
内存分析图:(注:本人也是初学者,如果发现错的地方,请指教!)
实例2:字符串拼接
public class Test{
public static void main(String[] args){
String str = "helloworld";
String str1 = "hello";
String str2 = "world";
String str3 = "hello" + "world";
String str4 = "hello" + str2;
String str5 = str1 + "world";
System.out.println(str1 == str2); //false
System.out.println(str == str3); //true
System.out.println(str == str4); //false
System.out.println(str == str5); //false
System.out.println(str4 == str5); //false
}
}
<1、常量与常量的拼接结果在常量池中。且常量池中不会存在相同内容的常量
<2、常量与常量拼接时,只要其中有一个是变量 ,结果就在堆中
❤️、使用相同的字符序列而不是使用new关键字创建的两个字符串会创建指向Java字符串常量池中的同一个字符串的指针。
实例3:
public class StringTest {
String str = new String( "good" );
char [] ch = { 't' , 'e' , 's' , 't' };
public void voidchange(String change(String str , char ch []) {
str = "test ok" ;
ch [0 ] = ] = 'b' ;
}
public static void main(String[] args ) {) {
StringTest ex = new StringTest();
ex.change(ex .str , ex .ch );
System.out .print( ex .str + " and ); //
System.out .println( ex .ch );
}
}
以上代码输出结果:
good and best
综合练习:
public class Test{
public static void main(String args[]) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("str1 and str2 are created by using string literal.");
System.out.println(" str1 == str2 is " + (str1 == str2));
System.out.println(" str1.equals(str2) is " + str1.equals(str2));
System.out.ptintln("-------------------------------------");
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println("str3 and str4 are created by using new operator.");
System.out.println(" str3 == str4 is " + (str3 == str4));
System.out.println(" str3.equals(str4) is " + str3.equals(str4));
System.out.ptintln("-------------------------------------");
String str5 = "Hel" + "lo";
String str6 = "He" + "llo";
System.out.println("str5 and str6 are created by using string constant expression.");
System.out.println(" str5 == str6 is " + (str5 == str6));
System.out.println(" str5.equals(str6) is " + str5.equals(str6));
System.out.ptintln("-------------------------------------");
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
System.out.println("str7 is computed at runtime.");
System.out.println("str8 is created by using string constant expression.");
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));
}
}
代码结果:
str1 and str2 are created by using string literal.
str1 == str2 is true
str1.equals(str2) is true
---------------------------------------------
str3 and str4 are created by using new operator.
str3 == str4 is false
str3.equals(str4) is true
---------------------------------------------
str5 and str6 are created by using string constant expression.
str5 == str6 is true
str5.equals(str6) is true
---------------------------------------------
str7 is computed at runtime.
str8 is created by using string constant expression.
str7 == str8 is false
str7.equals(str8) is true
注意:注意:注意:
String s = new String("abc"); //创建了几个对象
两个
第一个对象是"abc"字符串存储在常量池中;
第二个对象是创建在Heap(即堆)中的String对象;
这里的s是放在栈里面的指向了Heap堆中的String对象。
String s1 = new String("s1") ;
String s2 = new String("s1") ; //创建了几个对象
三个;
第一个是编译期就已经创建在常量池中创建的"s1",因为创建一个之后常量池中就会有,不再创建,直接指向;后面两个是运行期使用new创建在堆上的s1和s2;
**
**
new 出来的 String 类型是否也能使用常量池呢? 当然可以,就是通过 intern
方法。这个方法的意思就是先到缓存中(也就是常量池中)查询当前对象是否存在,存在就返回常量池中地址,不存在就加入常量池。
//双引号直接放入常量池
String s1 ="1";
String s2 =newString("1");
//false
System.out.println(s1 == s2);
//先到常量池中查询是否有”1“,存在就将常量池中对象返回,不存在就放到常量池中(此时常量池中存在s1)
//于是就将s1的值重新复制给s3,所以s1 == s3
String s3 =newString("1").intern();
//true
System.out.println(s1 == s3);
String t1 = new String("2");
解析:创建了两个对象,t1指向堆区
String t2 = "2";
解析:t2指向字符串常量池
t1.intern();
解析:字符串常量池已经存在该字符串,直接返回;
System.out.println(t1 == t2); //false or true
解析:很明显 false
String t3 = new String("2") + new String("2");
解析:过程同问题1 t3指向堆区
String t4 = "22";
解析:t4 在1.6 和 1.7中指向不同
t3.intern();
解析: 字符串常量池中已经存在该字符串 直接返回
System.out.println(t3 == t4); //false or true
解析: 很明显为 false 指向不同的内存区