String常量池面试题目汇总

一.常量池是什么

常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = “java”;可扩充( String.intern()方法 ),执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。

二.题目

I.以下两种创建字符串对象的方式有什么不同?

		String str1  =  new String("abc");
		String str2  =  "abc";
答:

在这里插入图片描述

  • 第一种方式先在堆(heap)中创建一个对象,然后在栈区创建一个String对象引用str1指向这个对象。若常量池中没有"abc"对象,则再创建一个"abc"对象放入常量池中。(运行时期创建)
  • 第二种方式先在栈区创建一个String的对象引用str2,然后去常量池中寻找有没有"abc"对象,如果有,直接将str2指向它;如果没有,先创建字符串对象"abc"放入常量池中,再将str2指向常量池中的"abc"常量。(编译期间执行)
注意:如果不清楚java字符串常量池里存的是String对象还是引用?

请到这位大神的博客中查看:
https://blog.csdn.net/shy244/article/details/80994059

II.下面语句将会创建几个对象

		String str1 = new String("A"+"B") ; 
		String str2 = new String("ABC") + "ABC" ; 
  1. str1:
    字符串常量池:“A”,“B”,“AB” : 3个
    堆:new String(“AB”) :1个
    引用: str1 :1个
    总共 : 5个
  2. str2 :
    字符串常量池:“ABC” : 1个
    堆:new String(“ABC”) :1个
    引用: str2 :1个
    总共 : 3个

III.true or false

		String str1 = "abc";				//pool
		String str2 = "abc";			  	//pool
		String str3 = new String("abc");		//heap
		String str4 = new String("abc");		//heap
		
		System.out.println(str1 == str2);		//1
		
		System.out.println(str2 == str3);		//2
		
		System.out.println(str3 == str4); 		//3
答:

true
false
false

  • 创建String对象引用str1,查看常量池中是否有"abc"对象;不存在,所以创建"abc"对象并放入常量池中,最后将str1指向常量池中的"abc"对象。
  • 创建String对象引用str2,发现常量池中已经有"abc"对象,直接将str2指向常量池中的对象。
  • 先在堆(heap)中创建一个对象,然后在栈区创建一个String对象引用str3指向这个对象。发现常量池中有"abc"对象,不再创建对象。
  • 先在堆(heap)中再创建一个对象,然后在栈区创建一个String对象引用str4指向这个对象。发现常量池中有"abc"对象,不再创建对象。
  1. 两个引用指向了同一个对象,返回true。
  2. str2指向常量池中对象,str3指向堆中对象,指的不是同一个对象,返回false。
  3. str3指向堆中对象,str3指向堆中对象,而两个指的不是同一个对象,返回false。

IV.true or false(接着上一题)

		String str5 = str4;				//heap
		String str6 = str4.intern();			//pool
		String str7 = str1;				//pool
		
		System.out.println(str4 == str5);		//1
		
		System.out.println(str4 == str6);		//2
		
		System.out.println(str1 == str2);		//3
		
		System.out.println(str1 == str7);		//4
答:

true
false
true
true

注意:public String intern():
返回字符串对象的规范化表示形式
返回一个字符串,内容与此字符串相同,但一定取自具有唯一字符串的池(常量池)。也就是“有就拿,没有放进去再拿”。
  • 创建str5引用并将其指向str4指向的对象,即堆中的一个"abc"对象。
  • 创建str6引用并将其指向str4指向的对象,即堆中的另一个"abc"对象。
  • 创建str7引用并将其指向str1指向的对象,即常量池中的"abc"对象。
  1. 两个引用指的都是堆中的同一个对象,即返回true。
  2. str4指的是堆中对象,而str6指的是常量池中的对象,即返回false。
  3. 两个引用指的都是常量池中的"abc"对象,即返回true。
  4. 两个引用指的都是常量池中的"abc"对象,即返回true。

V.true or false(接着上一题)

            str4.intern();
            System.out.println(str4 == str1);		//1	
           					
            str4 =  str4.intern();			//pool
            System.out.println(str4 == str1);		//2
答:

false
true

  1. 返回了str4指向的字符串对象的规范化表示形式(即找到了该对象在常量池中所对应的对象),却没有让str4接收(指向该规范化对象),即str4指向的对象仍然是堆中的对象,而str1指向的是常量池中的"abc"对象,即返回false。
  2. 两个引用都指向了常量池中的"abc"对象,即返回true。

VI.true or false

            String s1 = "Master";	
            String s2 = new String("Master");
            final String s3 = "Master";

            String s4 = "AndyMaster";			//pool
            String s5 = "Andy" + "Master";		//pool
            String s6 = "Andy" + s1;			//heap
            String s9 = "Andy" + s1;			//heap
            String s7 = "Andy" + s2;			//heap
            String s8 = "Andy" + s3;			//pool

            System.out.println(s4 == s5);		//1
            System.out.println(s4 == s6);		//2
            System.out.println(s4 == s7);		//3
            System.out.println(s4 == s8);		//4
            System.out.println(s6 == s9);		//5

答:

true
false
false
true
false

  1. s4,s5指向的对象都在常量池中,返回true。
  2. “Andy” + s1;**只要s1是变量,不论s1指向池中的字符串对象还是堆中的字符串对象,实际上是在堆上new出了个StringBuilder对象来进行append操作再toString()**而形成的。而s1指向的是常量池中的对象,即返回false。
  3. 同上,即返回false。
  4. 用final修饰的变量,编译器将其看成常量,编译器已知,直接用"Master"代替s3等效于"Andy" + “Master”。,即返回true。
  5. 创建了两个不同的StringBuilder对象,即返回false。

VII.字面量和常量池初探

字符串对象内部是用字符数组存储的,那么看下面的例子:

    String m = "hello,world";
    String n = "hello,world";
    String u = new String(m);
    String v = new String("hello,world");
  1. 会分配一个11长度的char数组,并在常量池分配一个由这个char数组组成的字符串,然后由m去引用这个字符串
  2. 用n去引用常量池里边的字符串,所以和n引用的是同一个对象
  3. 生成一个新的字符串,但内部的字符数组引用着m内部的字符数组
  4. 同样会生成一个新的字符串,但内部的字符数组引用常量池里边的字符串内部的字符数组,意思是和u是同样的字符数组

在这里插入图片描述

            String m = "hello,world";
            String n = "hello,world";
            String u = new String(m);
            String v = new String("hello,world");
            
            System.out.println(m == n); 
            System.out.println(m == u);
            System.out.println(m == v); 
            System.out.println(u == v);

答:

true
false
false
false

  1. m和n指向都是常量池中的对象
  2. m,u,v都是不同的对象
  3. m,u,v,n都使用了同样的字符数组,并且用equal判断的话也会返回true

参考:
https://segmentfault.com/a/1190000009888357
https://blog.csdn.net/xdugucc/article/details/78193805

原创文章 42 获赞 32 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_39671159/article/details/84311351