JAVA提升(六)——字符串在JVM中存放的位置(常量池)

常量池的作用:

在Java中只要是new的信息都会在上开辟一个新的空间,为了解决这个问题,JVM中才出现了字符串常量池的概念。但是只有直接用 ""修饰的字符,才会被加入到常量池中,当再次用 ""创建的时候,会首先从常量池中去获取

字符串常量池存在于运行时常量池中。也就存在于方法区中。(此处关于字符串常量池存放位置,这个是根据jdk版本不同而不同的,此处举例在方法区中。)


String 的特性:

<1、String类代表字符串。 Java 程序中的所有字符串面值(如 “abc” )都作 为此类的实例现。
<2、String String是一个 final类,代表不可变的字符序列 。
❤️、字符串是常量 ,用双引号起来表示。 它们的值在创建之后不能更改
<4、String 对象的字符 内容是存储在一个字符数组 value[] 中的

String类字符串比较:

实例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	
	}
}

内存分析图:(注:本人也是初学者,如果发现错的地方,请指教!)

JAVA提升(六)——字符串在JVM中存放的位置(常量池)_第1张图片

实例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

内存图:
JAVA提升(六)——字符串在JVM中存放的位置(常量池)_第2张图片


综合练习:

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;

**

String.intern()的使用

**

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.61.7中指向不同
t3.intern();
解析: 字符串常量池中已经存在该字符串 直接返回

System.out.println(t3 == t4); //false or true
解析: 很明显为 false 指向不同的内存区

你可能感兴趣的:(java,java)