您的位置:首页 > 编程语言 > Java开发

Java中String对象创建机制详解

2017-05-30 21:13 183 查看
Java中String对象创建机制总是令人困惑,我会尝试阐述清楚这一机制。额,太粗心把 Stack 拼作 Strack 了,我会尽快把图片和文章校对好。

 

1.创建方法

1、  直接使用""双引号创建:

String s1 = "first";

2、  使用newString()创建:

String s2 = new String();

3、使用newString("string")创建  :

String s3 = new String("string");

4、采用重载的字符串连接符创建:   

String s4 ="first" + "second";

 

2.知识准备

1. JVM



先需要了解下JVM 的内存区域组成,如果想要深入了解,可以参考深入理解JVM之JVM内存区域与内存分配– HelloCsl[1]。

在Java中String对象创建过程中,所用到的为这三者:



其中,Heap(堆)是JVM的内存数据区。Heap 的管理很复杂,是被所有线程共享的内存区域,在JVM启动时候创建,专门用来保存对象的实例。
MethodArea中有个区域被称为Constant Pool,是一个由数组组成的表,用来存储程序中的各种常量,包括Class、String、Integer等各种Java基本数据类型;String Pool是Constant Pool中存储String常量的区域;
而 VM Strack 中放置了对象的引用(reference类型,不等同于对象本身,根据不同的虚拟机实现,可能是一个指向对象起始地址的引用指针,也可能是一个代表对象的句柄或者其他与对象相关的位置)和 returnAdress类型(指向下一条字节码指令的地址)。
所以以上三者可以在此简单看作以下三者:



3.讲解[2]

注意了,每次讲解创建机制时三者的初始状态都是空白的。



还有,String的==和equals是不同的,==比较的是两个String在内存中的地址是否相同,equals比较的是两个String的值是否相同。所以,如果String是用双引号方式创建,则两个String都指向常量池中的同一个位置,这时==是成立的,equals也成立。如果String是用new方式创建的,两个String如果不是指向堆上的同一个String对象,则==不成立,而如果值相同,则equals成立[4]。

1. 直接使用" "双引号的创建机制

Strings1 = "first"; 
Stirngs2 = "first"; 
System.out.println(s1== s2); 



Strings1 = "first";
 


Stirngs2 = "first";
1、编译期:"first"是编译期常量,编译期就能确认它的值,在编译好的.class字节码文件中,"first"就已经存在String Pool中了;
2、运行期:JVM仅仅会查找维护常量池,拿着"first"在String Pool中查找是否存在内容相同的字符串(用equals()方法确认),如果存在,返回String Pool中相应内存单元的引用,赋值给s1(s1即是String Pool中存放"first"内存单元的地址);如果不存在,则创建一个"first"放在String Pool中,返回引用,赋值给s1;s2同理;
这个过程实际是调用intern()方法实现的;
此过程中,JVM绝不会在 Strack 创建String对象;
所以,上述代码,s1与s2指向String Pool中同一块内存区域,是同一个对象,故返回true

2. 使用new String()创建

String s3 = new String();



String s3 = new String()
 
 
在Java中,使用new关键字创建一个新对象,不管在Constant Pool中是否有值相同的对象,总会创建一个新的String对象存储在堆区(Strack)中,然后返回堆区(Strack)中相应内存单元的引用,赋值给s3;

3. 使用newString("string")创建;

String s4 = newString("string");

String s5 = newString("string");

System.out.println(s1 == s2);

 


String s4 = new String("string");
解释一下这行代码涉及的实例,一共两个,一个是字符串字面量" String "所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,另一个是通过new
String(“String”)创建并初始化的、内容与" String "相同的实例。
而变量就只有一个, String s4[3]。



String s5 = new String("string");
那么很明显,s4 !=s5;

4.采用重载的字符串连接符创建

    Stringa="ab"+"cd";
    Stringb="abcd";



String a="ab"+"cd";
"ab"和"cd"分别创建了一个对象,它们经过“+”连接后又创建了一个对象"abcd",因此一共三个,并且它们都被保存在字符串池里了[5]。
那么你认为 String b="abcd";会如何呢?



String b="abcd";
明白了吧。

 
参考网页:

[1] http://www.tuicool.com/articles/b6jUVn深入理解JVM之JVM内存区域与内存分配– HelloCsl

[2] http://blog.csdn.net/zhangliangzi/article/details/50075281Java中String对象创建机制详解(面试必问)
[3] http://www.cnblogs.com/YLsY/p/5729113.htmlJava中String两种不同创建方式的区别及intern的用法
[4] http://www.iteye.com/topic/774673 请别再拿“String s= new String("xyz");创建了多少个String实例”来面试了吧

[5] http://www.cnblogs.com/alexlo/archive/2013/02/21/2920209.htmlJava 由浅及深之 String 对象的创建及堆、栈的解释

 

时间:2017年5月26日22:28:35
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java JVM