对Java常量池与String 的 intern 方法的理解

对Java常量池与String 的 intern 方法的理解

intern是什么

​ String.intern() 是一个Native方法,它的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回常量池中代表这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中方,并且返回此String对象的引用。

方法的声明:

public native String intern();

intern的作用:

​ intern()方法设计的初衷,就是重用String对象,以节省内存消耗。

String的几种创建方式
  1. String s = "hello "+"world";//等价于直接赋值"hello world"
    

    ​ 这种方式在编译阶段会合成一个字符串

  2. String s1="world";
    String s = "hello "+s1;
    

    ​ 以上代码实际运行过程

    String s1="world";
    StringBuilder sb=new StringBuilder("hello");
    sb.append(s1);
    String s = sb.toString();
    
  3. String s=new String("hello ") + new String("world");
    

    ​ 此种同样是StringBuilder的拼接

使用intern的例子,理解intern原理

例1:

 String str1 = new String("coo")+new String("hua");
 System.out.println(str1.intern()==str1);
 System.out.println(str1=="coohua");
(jdk1.8)运行结果:
    true
    true

例2:

String st = "coohua";
String str1 = new String("coo")+new String("hua");
System.out.println(str1.intern()==str1);
System.out.println(str1=="coohua");
(jdk1.8)运行结果:
    false
    false

​ 对比以上两个样例代码,发现只存在一行代码的区别,运行的结果截然不同。这种现象的产生,就是由于intern()方法造成的。在JVM运行时数据区中的方法区有一个常量池,但是在JDK1.6以后,常量池被放置在了堆空间。在JDK1.6,JDK会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中的这个字符串实例的引用。而JDK1.7及以后的intern不再复制实例,只是在常量池中记录首次出现的实例引用。

​ String可通过字面量赋值,也可以通过new String() 创建对象。 通过字面量赋值创建字符串时,会先在常量池中查找是否已经存在相同的字符串,倘若已经存在,栈中的引用直接指向该字符串;倘若不存在,则在常量池中生成一个字符串,再将栈中的引用指向该字符串。而通过new的方式创建字符串时,就直接在堆中生成一个字符串的对象,栈中的引用指向该对象。

图示:

img

知识点备案

常量池

​ Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。

​ 静态常量池指的时候 *.class 文件中的常量池, *.class 文件中的常量池不仅仅包含字符串(数字)的字面量,还包含类、方法的信息。

​ 运行时常量池则是在jvm虚拟机完成类装载操作后,将 class 文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池(jdk1.6及之前),jdk1.6以及之后常量池被移到了堆空间。

常量池的好处

​ 常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。

​ 例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
​ (1)节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
​ (2)节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用判断引用是否相等,也就可以判断 实际值是否相等。

注意:

​ JDK1.7开始,常量池由方法区(永久代)迁移至堆空间。对intern产生的影响:

JKD1.6及之前:

​ 如果运行时常量池中已经包含一个等于此String对象内容的字符串,则返回常量池中该字符串的引用;如果没有,则在常量池中创建与此String内容相同的字符串,并返回常量池中创建的字符串的引用。

JDK1.6之后:

​ 当常量池中没有该字符串时,JDK7的intern()方法的实现不再是在常量池中创建与此String内容相同的字符串,而改为在常量池中记录java Heap中首次出现的该字符串的引用,并返回该引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值