String.intern() 详解

Posted zriib58v

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了String.intern() 详解相关的知识,希望对你有一定的参考价值。

使用 String.intern() 可以保证相同内容的字符串变量引用同一的内存对象

基本类型常量池

常量池就类似一个JAVA系统级别提供的缓存,基本类型对应的缓冲池如下:

  • boolean values true and false
  • all byte values
  • short values between -128 and 127
  • int values between -128 and 127
  • char in the range \\u0000 to \\u007F

常量池并不是创建时都会用到,比如 new Integer(123) 与 Integer.valueOf(123)

  • new Integer(123) 每次都会新建一个对象
  • Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用

String常量池

它的主要使用方法有两种:

  • 直接使用双引号声明出来的String对象会直接存储在常量池中。
  • 如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中

接下来我们主要来谈一下String#intern方法。

String#intern方法是一个 native 的方法,如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回。

查看你jdk源码可以发现,它的大体实现结构就是: JAVA 使用 jni 调用c++实现的StringTableintern方法, StringTableintern方法跟Java中的HashMap的实现是差不多的, 只是不能自动扩容。默认大小是1009。

要注意的是,String的String Pool是一个固定大小的Hashtable,默认值大小长度是1009,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern时性能会大幅下降(因为要一个一个找)。

例子

String s = new String("abc")这个语句创建了2个对象,第一个对象是”abc”字符串存储在常量池中,第二个对象在JAVA Heap中的 String对象

public static void main(String[] args) { 
    String s = new String("1"); 
    s.intern(); 
    String s2 = "1"; 
    System.out.println(s == s2); 
    String s3 = new String("1") + new String("1"); 
    s3.intern(); 
    String s4 = "11"; 
    System.out.println(s3 == s4); 
}

打印结果是

  • jdk6 下false false
  • jdk7 下false true

    public static void main(String[] args) { 
    String s = new String("1"); 
    String s2 = "1"; 
    s.intern(); 
    System.out.println(s == s2); 
    String s3 = new String("1") + new String("1");
    String s4 = "11"; 
    s3.intern(); 
    System.out.println(s3 == s4); 
    }

    打印结果为:

  • jdk6 下false false
  • jdk7 下false false

jdk7 版本对 intern 操作和常量池都做了一定的修改。主要包括2点:

  • 将String常量池 从 Perm 区移动到了 Java Heap区
  • 使用String#intern 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。

参考原文:深入解析String#intern

以上是关于String.intern() 详解的主要内容,如果未能解决你的问题,请参考以下文章

String类中intern方法的原理分析

对String.intern()的理解

浅析String.intern()方法

Java必修课String.intern()原来还能这么用(原理与应用)

Java必修课String.intern()原来还能这么用(原理与应用)

JDK方法区元空间以及String.intern()知识要点