美文网首页
String中有趣的intern函数

String中有趣的intern函数

作者: 阿斯巴甜不太甜 | 来源:发表于2019-08-15 22:12 被阅读0次

!!注意 本文讨论的是jdk1.7后的intern()特性

先说.intern()这个方法是做什么的:返回这个字符串在字符串常量池中的地址。
再来看下面这段懵逼的代码:

        String s = new StringBuilder("ja").append("va").toString();
        String s1 = new StringBuilder("计算机").append("软件").toString();
        String s2 = new StringBuilder("计算机122").append("软件").toString();    
        String s3 = "绝对权威";
        String s4 = new String("撒旦大神大神dqw");
        String s5 = new String("jdiqwsad ");
        String s6 = "jdiqwsad " ;
        System.out.println(s.intern()==s);
        System.out.println(s1.intern()==s1);  //true
        System.out.println(s2.intern()==s2);  //true
        System.out.println(s3.intern()==s3);  //true
        System.out.println(s4.intern()==s4);  //false
        System.out.println(s5.intern()==s6);  //true
        System.out.println(s4.toString()==s4.intern());//false

是不是一脸懵逼?再来解释一下开头所说的意思。

实际上我们知道JVM中存储对象实例的地方是栈,存储常量的地方是方法区,而方法区中有一块专门的内存专门存储字符串,这块内存就叫做字符串常量池。

而s.intern()(假设s="abc")方法的工作机制是:首先检测字符串常量池中是否存在"abc",如果存在,就直接将常量池中“abc”的地址返回;如果不存在,就在常量池中记录“abc”首次出现的地址。

如过s="abc",那"abc"就是在常量池生成,s.intern()返回的就是常量池中的地址;如果是s=new String("abc")呢?这里分了两步:第一步在编译的时候已经把abc放到常量池里去了,然后用new生成的“abc”放在堆里,而s指向的是堆里的对象,也就是说这一条语句产生了两个对象;而s=new String("a")+"bc"就可以让常量区中只保留“abc”在堆中的引用。

字符串常量池中存的字符串可能为堆中的引用也可能是该字符串本身就存在于常量池——取决于该字符串首次出现的地方,而intern()的作用域一定是字符串常量池,即使返回的值可能是堆的地址,但也是从字符串常量池中获取的

我们再来看代码,先不看s(s比较特殊,最后来说明),从s1开始讲起,通过调用StringBuilder之后,是默认会在堆中建立一个字符串对象“计算机软件”的,然后再在常量池中记录这个堆的地址,那么s1显然是指向堆的,而s1.intern()从常量池中获取的是“计算机软件”首次出现的地址,也是堆。那就不难理解s1.intern()==s1为true了。同理有s2。

s3的话是显示声明的字符串,在编译期就在常量池中生成了,所以s3指向的是常量池,s3.intern()也是。

这里强调一下为什么这里的字符串都用append连接生成,因为显示的直接放入构造函数中的话,会在编译期就于常量池中生成该字符串,也就是说之后不管怎样intern()获取到的首次出现的地址都在常量池。

再看s4,再强调一遍!划重点同学们!显示声明的字符串会在编译期就生成于常量池,intern()返回的一定是常量池的引用!而s4,由于是使用了new新建一个字符串,那s4一定是指向堆的地址的,那显然s4.intern()==s4为false,也就是说"撒旦大神大神dqw"这个字符串在常量池和堆中都存在,而s4.intern()和s4分别对应了两个位置的地址。你们不妨试下s4=new String("撒旦大神")+"大神dqw";这样构造,再看看s4.intern()==s4的结果。

再来看s5和s6,s5已经知道是指向堆了,s5.intern()也知道是指向字符串常量池(再强调一遍,显示声明),那s6显然也是,那显然s5.intern()==s6为true。

s4.toString()==s4.intern()就更不用说了吧,s4.toString返回的就是自己指向的位置。

为什么s.intern()==s放在最后说呢?因为这个比较特殊,特殊在哪?特殊在java这个单词!“java”这个单词实际上一开始就存在于字符串常量区了,然后s显然是指向堆的,结果就是False,我也觉得很奇怪。我猜想是JVM初始化的时候常量池中本身是存在一些字符串的,其中就包括了"java"

大概就这么多了,看了我一晚上才基本上搞明白,有用请点赞哦谢谢

相关文章

网友评论

      本文标题:String中有趣的intern函数

      本文链接:https://www.haomeiwen.com/subject/svytsctx.html