首页 > 编程 > Java > 正文

Java堆、栈、常量池、String

2019-11-11 07:51:21
字体:
来源:转载
供稿:网友
● 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new出来的对象)或者常量池中(字符串常量对象存放在常量池中。)● 堆:存放所有new出来的对象。● 常量池:存放字符串常量和基本类型常量(public static final)。字符串常量池既不在堆中也不在栈中,是独立的内存空间管理(方法区中)。对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等(仅仅是值相等)的字符串,在常量池中永远只有一份,在堆中有多份。String创建对象的两种方式(1) String str = "abc";    创建对象的过程:    ① 首先在常量池中查找是否存在内容为"abc"字符串对象    ② 如果不存在则在常量池中创建"abc",并让str引用该对象    ③ 如果存在则直接让str引用该对象(2) String str = new String("abc");    创建实例的过程:    ① 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象    ② 在字符串常量池中查看,是否存在内容为"abc"字符串对象    ③ 若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来    ④ 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来    intern() 方法可以返回该字符串在常量池中的对象的引用代码测试:public class StringTest {    public static void main(String[] args) {        String s1 = "abc";        String s2 = "ab";        String s3 = "c";        String s4 = "ab" + "c";        String s5 = s2 + s3;        String s6 = new String("abc");        String s7 = s6.intern();        System.out.PRintln(s1 == s4); // ①        System.out.println(s1 == s5); // ②        System.out.println(s1 == s6); // ③        System.out.println(s1 == s7); // ④        System.out.println(s6 == s7); // ⑤    }}结果分析:① true    因为String s4 = "ab" + "c";会先查找常量池中是否存在内容为"abc"的字符串对象,若存在则直接让s4引用该对象,显然String s1 = "abc";会在常量池中创建"abc"对象,所以s1引用该对象,s4也引用该对象,所以S1 == S4为true。② false    因为String s5 = s2 + s3;涉及到变量的相加,会产生新的对象,其内部实现是先new一个StringBuilder,然后append(s2),append(s3),然后让s5引用toString()返回的对象。(若想了解更多细节,可以查看反编译的代码)。③ false    String s1 = "abc";------在常量池中建立一个"abc",s1指向"abc";引用s1存储的是"abc"在常量池的地址。    String s6 = new String("abc");------在堆上分配内存,引用s6存储的是new String("abc") 在堆上的内存地址。    还有一点区别是s1在类加载时就完成了初始化,而s6 要在执行引擎执行到那一行代码时才完成初始化。④ true    String s7 = s6.intern();中intern 方法返回s6在常量池中的对象的引用,在字符串常量池中查看,是否存在与字符串s6的内容"abc"相等的字符串对象,此处已经存在String s1 = "abc";已经存在内容为"abc"的字符串对象。⑤ false    此处String s7 = s6.intern();等同于String s7 = "abc";    与③同理。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表