首页
IT
登录
6mi
u
盘
搜
搜 索
IT
Java堆、栈、常量池、String
Java堆、栈、常量池、String
xiaoxiao
2021-03-26
27
● 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(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"; 与③同理。
转载请注明原文地址: https://ju.6miu.com/read-663016.html
技术
最新回复
(
0
)