自动内存管理之【常量池】

首先上一段代码,一起思考,打印的结果,基于jdk1.8。

        StringBuilder sb=new StringBuilder("我爱我媳妇儿");
        String s= sb.toString();
        System.out.println(s.intern()==s);  //false
        sb.append(",她也很爱我!");
        s=sb.toString();
        System.out.println(s.intern()==s);  //true
        StringBuilder stringBuilder = new StringBuilder("ja").append("va");
        String s2=stringBuilder.toString();
        System.out.println(s2.intern()==s2);//false

这里说一些String类的intern方法,它是一个本地方法。Api对它的解释是

Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

翻译过来的结果是:返回字符串对象的规范表示形式。字符串池最初是空的,由类String私下维护。当调用intern方法时,如果池中已经包含一个等于equals(object)方法确定的string对象的字符串,那么将返回池中的字符串。否则,该String对象将被添加到池中,并返回对此String对象的引用。因此,对于任何两个字符串s和t,s.inter()==t.inter()为真当且仅当s.equals(t)为真。

看到这里的朋友应该有点感觉了,我标红的地方是重点。

俗话说“万丈高楼平地起,辉煌智能靠自己”,要明白常量池 。何为常量池?

常量池分为:静态常量、全局常量、局部常量。

java中常量用final定义,也就是说不可变的值都会放到常量池中。比如int i=8,这个8是个不可变的值,string v="我爱我老婆",这个值就是常量。就是不可变的值就是常量,这些数据在编译的时候就会自动放到常量池中。

弄明白了这个,我们来分析上面的结果:

        StringBuilder sb=new StringBuilder("我爱我媳妇儿");
        String s= sb.toString();
        System.out.println(s.intern()==s);  //返回的是sb

首先这里说明一下,常量池和堆的关系,这是重点!!!!!!前提背景是jdk1.8

系统在编译期间将“我爱我媳妇儿”常量添加到了常量词,到第二行的s指向的是堆对象的引用,而s.intern是常量词的引用。所以这里会出现false的情况。

为什么在 sb.append(",她也很爱我!");之后又为true呢?

首先“,她也很爱我”会放到常量池中,在sb.toString()环节中将“我很爱我媳妇儿,她也很爱我”放到堆中。在变量s就会指向堆中的地址,当s.intern()进行查找的时候发现常量池中不存在,便会在常量池中创建,并执行堆中sb.toString()的地址。所以就是结果就是True。

那为什么输出Java那个又是false呢?

根据上面的这个思路我们去分解步骤,首先在常量词中分别创建了“ja”,“va”的常量。stringBuilder.toString()的时候在堆中进行了创建。这时候栈中的s2就会指向堆中“java”的地址,但是当s2.intern()被调用的时候,就会在常量池中进行查找,常量池中存在一个“java”的常量,将其返回。但是其对象的引用与我们的不一致。所以为false。

自动内存管理之【常量池】_第1张图片

 这上面的难点为:1、弄清楚什么叫常量 2、对象存放的位置 

你可能感兴趣的:(深入理解Java虚拟机,java,服务器,开发语言)