一次性记住String和intern的内存特性

本文介绍了String的intern方法在JDK1.7前后的区别。JDK1.6会在常量池无相同字符串引用时拷贝对象,而JDK1.7以后常量池存的是指向堆的引用。还提到判断字符串对象是否为同一对象的要点,最后给出测试代码及解释。

String的intern方法在jdk1.7以后发生了改变,主要区别如下

1. jdk1.6的版本,先查找常量池中有无相同字符串的引用,若有,则返回该字符串对象,若无,则拷贝字符串对象到常量池中,返回常量池的对象

2.jdk1.7以后的版本中,字符串在常量池的存在不再是字符串对象,而是一个指向堆的引用。具体为:

(1)执行intern时,如果字符串没有出现过,则在常量池记录首次出现的该字符串的实例的引用

(2)如果出现过,则返回实例的引用

 

在判断字符串对象是否统一对象中,除了以上的特性,还必须清楚

1.已确定的字符串在编译器就已经在常量池存在引用

2.java等特殊的字符串在某些时刻已经被加载到常量池中

 

以下为String的测试代码,代码结果的解释在注释中备注

        String str1 = new String("ABC");  // 创建了一个新的对象
    	String str2 = "ABC"; // 从常量池查找ABC若有则返回常量池中的引用,若不存在则在常量池生成一个ABC,返回引用
    	System.out.println( str1 == str2); // 为false,因为str2是常量池的引用,str1是在堆中新建的引用
    
    	System.out.println( str1.intern() == str2); // 为true, str1.intern 先去常量池查找有无字符串,有则返回了引用,与str2一致
    	
    	str1 = new String("计算机");
    	// 确定的字符串在编译器就已经在常量池存在引用
    	System.out.println( str1.intern() == str1); // 为false, 
    	// 因为“计算器”字符在编译阶段就创建到常量池了,常量池的地址与java堆中new出来的地址肯定不同
    	
    	
    	str1 = new StringBuilder().append("中").append("国").toString();
    	// StringBuilder 创建了字符串,
    	// str1.intern 先去常量池查找有无字符串,
    	// 若无,jdk1.6会拷贝字符串到常量池中,返回常量池到引用,
    		// jdk1.7以上会将首次出现字符串到引用放到常量池中,返回常量池到地址
    	System.out.println(str1.intern() == str1); // true// 在jdk1.6中是false
    	
    	str1 = "ja"+"va";
    	// str1 在编译阶段就知道是java了,在常量池中,str1
    	System.out.println(str1.intern() == str1); // true
    	String s1 = "abc"; 
    	String s4 = "a" + "bc"; 
    	System.out.println("测试编译阶段字符串+的结果," + (s1 == s4)); 
    	
    	
    	str1 = new StringBuilder().append("ja").append("va").toString();
    	System.out.println(str1.intern() == str1); // false ,
    	// java 字符串在某个时刻已经被加载到常量池中,str1.intern 返回了首次出现java到实例引用,与str1的对象不同

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值