Java中String对象创建机制详解

来源:互联网 发布:数据库设置主键的语句 编辑:程序博客网 时间:2024/05/16 15:29

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

原创粉丝点击