StringTable面试题,常量池在内存中的位置,串池概念

本文详细介绍了Java中的字符串常量池(Stringtable)的概念,包括其内存位置的变迁,以及字符串对象如何通过intern()方法与常量池交互。通过分析代码示例,解释了不同字符串拼接方式在常量池中的表现,讨论了JDK1.6与JDK1.8之间的差异,强调了 intern() 方法的作用和内存管理的重要性。
摘要由CSDN通过智能技术生成

1、概念:
1、String table又称为String pool,字符串常量池,其存在于堆中(jdk1.7之后改的)。最重要的一点,String table中存储的并不是String类型的对象,存储的而是指向String对象的索引,真实对象还是存储在堆中。
2、此外String table里面不存在相同的两个字符串。
3、此外String对象调用intern()方法时,会先在String table中查找是否存在于该对象相同的字符串,若存在直接返回String table中字符串的引用,若不存在则在String table中创建一个与该对象相同的字符串。

2、StringTable在内存中的位置:(存在堆内存中JDK1.8,JDK1.6在永久代的常量池中)

在这里插入图片描述

3、常量池在内存中的位置:

在这里插入图片描述

4、面试题代码:

public class StringTest {
	public static void main(String[] args) {
		// StringTable串池 ["a","b","ab"]
		String s1 = "a";
		String s2 = "b";
		String s3 = "a" + "b"; 
		String s4 = s1 + s2; 
		String s5 = "ab"; 
		String s6 = s4.intern();
		
		
		// 问
		System.out.println(s3 == s4); // false
		System.out.println(s3 == s5); // true
		System.out.println(s3 == s6); // true
		
	    // 问,如果调换了【最后两行代码】的位置呢,如果是jdk1.6呢
        String x2 = new String("c") + new String("d"); 
	    String x1 = "cd";
	    x2.intern();
	    System.out.println(x1 == x2); // false
		

		String x2 = new String("c") + new String("d");
		x2.intern();
		String x1 = "cd";
		System.out.println(x1 == x2);// true,如果是JDK1.6,此时就是false,
	}

}

5、原理解释:


public class StringTest {
	public static void main(String[] args) {
		// StringTable串池 ["a","b","ab"]
		String s1 = "a";
		// 常量池中的字符串仅是符号,第一次用到时才变为对象 ,没用到的时候就在常量池中,第一用到时才变为对象,
		// 如果此时串池(StringTable)中没有"a",就直接存放在串池中,如果串池中有"a",就返回"a"的对象给s1,利用串池的机制,来避免重复创建字符串对象 
		String s2 = "b";
		
		// 字符串常量拼接,字符串常量拼接的原理是编译期优化 ,如果串池中有"ab",就直接将引用指向该"ab",如果没有就将"ab"对象放入串池中
		String s3 = "a" + "b"; 
		// 字符串变量拼接的原理是 StringBuilder (1.8),底层调用StringBuilder,
		// 分别将s1(a)和s2(b)拼接到一起,并创建一个新的String对象 ,在堆中存放,并没有放到串池中
		String s4 = s1 + s2; 
		// 此时串池中已经有了"ab",所以就直接将"ab"(s3)的对象返回给了s5,所以s3和s5的地址是相等的
		String s5 = "ab"; 
		// 此时s4对象调用intern()试图将s4对象放入串池,由于串池中已经有了"ab"对象,所以没能将s4对象放入串池中,s4此时还是存放在堆中,
		// 而是将串池中的"ab"(s3)对象返回给了s6,所以s3的地址和s6的地址相同。
		String s6 = s4.intern();
		
		
		// 问
		System.out.println(s3 == s4); // false
		System.out.println(s3 == s5); // true
		System.out.println(s3 == s6); // true
		
		// StringTable串池 ["a","b","ab","c","d","cd"]
		// 此写法是先将字符串常量"c","d"放入常量池中,再new对象,最后通过StringBuilder来将字符串拼接,最后创建String("cd"),其对象放在堆内存中
//		String x2 = new String("c") + new String("d"); 
		// 由于此时串池中没有"cd",就直接将"cd"(x1)存放到串池中,
//		String x1 = "cd";
		// x2对象调用intern()来将x2存放到串池中,但是此时串池中已经有了"cd",故没有将X2对象存入串池中,此时X2对象存放在堆中,所以X1和X2的地址不相等。
//		x2.intern();
		
//		 System.out.println(x1 == x2); // false
		
		// 问,如果调换了【最后两行代码】的位置呢,如果是jdk1.6呢 System.out.println(x1 == x2);
		// StringTable串池 ["a","b","ab","c","d","cd"(X2)]
		// 此写法是先将字符串常量"c","d"放入常量池中,再new对象,最后通过StringBuilder来将字符串拼接,最后创建String("cd"),其对象放在堆内存中
		String x2 = new String("c") + new String("d");
		// X2调用intern方法试图将X2对象放入串池中,由于串池中没有"cd",故直接将X2("cd")存入串池中,X2的地址现在串池中
		x2.intern();
		// 此时串池中已经"cd"(X2),因此没有将这个"cd"存入串池中,而是将X2("cd")的对象返回给了X1,所以X1的地址就和X2的地址相等
		String x1 = "cd";
		System.out.println(x1 == x2); // true,如果是JDK1.6,此时就是false,因为,X2在调用intern()时,串池中没有"cd",就将X2的对象复制一份存入到串池中
		// 此时串池中的存的是X2复制的新对象,String x1 = "cd";执行这行代码时,由于串池中存着X2复制的新对象"cd",所以将这个新对象的地址返回给了X1,所以最终X1和X2的地址不相等。
		//可以使用 intern 方法,主动将串池中还没有的字符串对象放入串池
		//1.8 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池, 会把串 池中的对象返回 
		//1.6 将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有会把此对象复制一份, 放入串池, 会把串池中的对象返回

		
	}

}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值