Java的String.intern()方法

251 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

什么是intern方法

一个native的方法

作用:声明一个String对象,去常量池中查询是否该对象,如果不存在就将这个字符串放入常量池中(一判断二存入)

(在JDK7及其之后,同时会检查堆中是否有这个对象,如果有就直接在字符串常量池中保存堆中那个对象的地址)

String s="蛋炒饭"String s=new String("蛋炒饭").intern()都会将“蛋炒饭”放入常量池中。(ps:String s=new String("蛋炒饭")会在堆中生成一个对象、在常量池中生成一个对象;并返回堆中生成对象的地址)


public class StringInternTest{
  	public static void main(String[] args){
      	String s=new String("1");//创建了对象,s中保存的是对象在堆中的地址信息
      	s.intern();//此时是将"1"放入字符串常量池中。但是已经有了,所以该操作相当于什么都没做,只是返回了字符串常量池中的地址信息。但是没有接收
      	String s2="1";//返回字符串常量池"1"的地址信息
      	System.out.println(s==s2);
      
      	String s3=new String("1")+new String("1");//创建了"1"的对象,并在常量池中生成了"1"(忽视上面)。创建了"11"的对象,将对象在堆中的地址赋值给了s3
      	s3.intern();//将"11"放到字符串常量池中
      	//JDK6,将"11"当到了永久代中的字符串常量池中
      	//JDK7~,欲要将"11"放到堆的字符串常量池中,但是发现堆空间中有"11"的对象,所以字符串常量池中记录的就是堆空间这个对象的地址信息
      	String s4="11";//获取字符串常量池中的"11"的地址信息
      	System.out.println(s3==s4);//JDK6-false,JDK7-true
    }
}

JDK6:false、false

s!=s2:s是通过new出来的,保存的是堆中的地址。s2是获取的"1"常量池中的地址

s3!=s4:s3经过intern()之后会在字符串常量池中创建"11"

JDK7/8及其之后(和6的区别就是字符串常量池从永久代到了堆中):false 、true

s!=s2:s是通过new出来的,保存的是堆中的地址。s2是获取的"1"常量池中的地址

s3==s4:s3经过intern()之后发现堆中有这个对象,所以就直接在字符串常量池中记录的是堆中这个对象的地址信息

为什么要使用intern(),节省空间,垃圾回收

arr[i]=new String(String.valueof(data[i].intern()))

调用intern()的时候,会返回对应的字符串常量池中的地址信息。则数组中存储的就是字符串常量池中的地址信息。然后创建在堆中的字符串对象因为没有引用会被垃圾回收给回收掉。

  1. 赋值的时候使用的是字符串常量的地址信息
  2. 原本创建的堆中对象因为没有使用会被回收

总结:大量使用字符串的时候,推荐增加使用intern()来大大节省内存空间。