java中的字符串到底是在方法区的常量池里还是new出来的对象里 - Go语言中文社区

java中的字符串到底是在方法区的常量池里还是new出来的对象里


String实质是字符数组,两个特点:1、该类不可被继承;2、不可变性(immutable)

例如 String s1 = new String("myString");

和 String s1 = "myString"; 

第一种方式通过关键字new定义过程:在程序编译期,编译程序先去字符串常量池检查,是否存在“myString”,如果不存在,则在常量池中开辟一个内存空间存放“myString”;如果存在的话,则不用重新开辟空间,保证常量池中只有一个“myString”常量,节省内存空间。然后在内存堆中开辟一块空间存放new出来的String实例,在栈中开辟一块空间,命名为“s1”,存放的值为堆中String实例的内存地址,这个过程就是将引用s1指向new出来的String实例

第二种方式直接定义过程:在程序编译期,编译程序先去字符串常量池检查,是否存在“myString”,如果不存在,则在常量池中开辟一个内存空间存放“myString”;如果存在的话,则不用重新开辟空间。然后在栈中开辟一块空间,命名为“s1”,存放的值为常量池中“myString”的内存地址

转载自:https://zhidao.baidu.com/question/1431032825282549579.html

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


就速度来说,有如下关系: 

    寄存器 > 栈 >堆 >其他

这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。


    对于字符串:

其对象的引用都是存储在栈中的,

如果是编译期已经创建好(即直接用双引号定义的)的就存储在常量池中

如果是运行期(即new出来的)才能确定的就存储在堆中

对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。


如以下代码:

Java代码  

String s1 = "china";  

String s2 = "china";  

String s3 = "china";  

String ss1 = new String("china");  

String ss2 = new String("china");  

String ss3 = new String("china");  

 

对于通过 new 产生一个字符串(假设为 ”china” )时,会先去常量池中查找是否已经有了 ”china” 对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此 ”china” 对象的拷贝对象。并把ss1指向堆中的地址。(在常量池中创建目的是为了提升字符串的访问效率


再例子:

String s5 = new String("Hello"); //先在常量池中创建,再在堆中创建,返回的数值s5是堆中的地址
String s6 = s5.intern();         //返回的数值s6 ,是常量池中的地址
String s10 = "Hello";            //返回的数值s10,是常量池中的地址

System.out.println(s5 == s6);   //输出false

System.out.println(s6 == s10);  //输出true



这也就是有道面试题:

 String s = new String(“xyz”); 产生几个对象?一个或两个,如果常量池中原来没有 ”xyz”, 就是两个。

 

对于基础类型的变量和常量:变量和引用存储在栈中,常量存储在常量池中。


转载自:https://blog.csdn.net/u012031380/article/details/54981472


版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/HD243608836/article/details/79966025
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 01:18:41
  • 阅读 ( 1039 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢