对String中intern()方法的认识

最近在看字符串相关知识的时候,又看到了关于字符串创建方式和是否相等的相关问题,回忆起之前碰到的一个String中的intern()方法,它是一个本地方法(由Java语言外的语言编写),因此在jdk1.8源码中没有其实现,不过有一段描述,讲述了它的作用。
intern()方法的描述

    /**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     */
      public native String intern();

归纳一下的话,它的作用在jdk1.7之后是查看常量池中是否存在和调用方法的字符串内容一样的字符串,如果有的话,就返回该常量池中的字符串,若没有的话,就在常量池中写入一个堆中该字符串对象的一个引用,指向堆中的该对象,并返回该引用。
用代码说话吧,注释中有我对intern()方法的理解,过程中查阅了部分源码和相关博客,如果有谬误,请大家指出,互相交流学习,共同进步。
intern方法的测试

public class InternTest {
    public static void main(String[] args) {
        String a = new String("abc");
        // 第一次,创建了两个对象,一个是堆中的string对象,一个是常量池中的"abc"
        String b = new String("abc");
        // 第二次,创建一个对象,堆中的另外一个string对象
        System.out.println(a.intern() == b.intern());// true
        System.out.println(a.intern() == b);// false
        System.out.println(a.intern() == a);// false
        /*
         * intern方法会到常量池中查找是否存在该对象,如果存在,返回该对象。不存在的话就创建该对象并返回该对象(jdk1.6),(jdk1.7)
         * 会在常量池中存一个指向堆中的那个对象的引用。 不存在往往是String s3 = new String("1") + new
         * String("1");这种形式,会在堆中有一个s3指向的11的对象和常量池中的1对象
         * 在这里就是体现的堆中的内存地址不一样,但对应的同一个常量池中的string 第一个比较时常量池中的该对象和自身比较
         * 下面两个比较则是常量池中的对象和堆中的两个对象进行比较
         */
        String poolstr = "abc";
        // 直接从字符串常量池中获取
        System.out.println(a.intern() == poolstr);// true
        System.out.println(b.intern() == poolstr);// true
        /*
         * 这里新声明并赋值了一个poolstr,值为常量池中的字符串"abc",将它和a.intern()和b.inten()比较就是和自身比较
         */
        String str = new String("a") + new String("b");
        System.out.println(str.intern() == str);// true
        /*
         * str创建了3个对象,在堆中有一个"ab",在常量池中有一个"a"和"b" 比较str.intern()和str会得到true
         * 在jdk1.7之后,会在常量池中存一个指向堆中的那个对象的引用。
         * 调用str.intern()会在常量池中存储一个指向堆中"ab"的引用,也就是说它和堆中的对象实际是等价的,因此==时返回true
         */
        String strtwo = "ab";
        System.out.println(strtwo == str);// true
        /*
         * 常量池中已存在ab,所以会直接将strtwo指向常量池中的"ab",即堆中str对象的引用,因此相等
         */
    }
}

其中有提到一个new String(“”)会创建几个对象,一般就是一个或两个,主要是看常量池中是否已经有了该字符串,在上述代码在也有所提及。
对于每一个比较语句我都做了自己的理解的标注,比较通俗易懂,仔细看一下就能理解intern方法的作用,另外附上一篇博文,是一篇讲述intern方法的实现原理的博文,对我理解intern方法有很大帮助,感兴趣的朋友可以看一下。
Java技术——你真的了解String类的intern()方法吗
其中提到了jdk1.7将常量池从方法区中转移到堆中对intern()方法的影响,非常清晰的描述了差别,配合本博文实例更适宜使用,本博文更多的从实现角度来解析intern()方法,希望对您有所帮助
如有谬误,敬请指正。
欢迎讨论。

  • 10
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值