java string对象创建对象_Java中String对象创建机制详解

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

dce1910aa033e0189eb762042070a369.png

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

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

eadbda0b135cc4f2fef23322a4d20124.png

其中,Heap(堆)是JVM的内存数据区。Heap 的管理很复杂,是被所有线程共享的内存区域,在JVM启动时候创建,专门用来保存对象的实例。

MethodArea中有个区域被称为Constant Pool,是一个由数组组成的表,用来存储程序中的各种常量,包括Class、String、Integer等各种Java基本数据类型;String Pool是Constant Pool中存储String常量的区域;

而 VM Strack 中放置了对象的引用(reference类型,不等同于对象本身,根据不同的虚拟机实现,可能是一个指向对象起始地址的引用指针,也可能是一个代表对象的句柄或者其他与对象相关的位置)和 returnAdress类型(指向下一条字节码指令的地址)。

所以以上三者可以在此简单看作以下三者:

81935c28fb84a182540c2f6cf6b4d2c6.png

3.讲解[2]

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

709777ecdccfd67bfc47ace400150a79.png

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

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

Strings1 = "first";

Stirngs2 = "first";

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

73c768fad28f7ca34fb2f01a008d3e9d.png

Strings1 = "first";

0fd266c6ec3a4291956e3295f2906898.png

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();

7eb6ddd92211e1d5aa91494d69e176c7.png

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);

7041f63bce730c7fbfa61dd93287f3f9.png

String s4 = new String("string");

解释一下这行代码涉及的实例,一共两个,一个是字符串字面量" String "所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,另一个是通过new

String(“String”)创建并初始化的、内容与" String "相同的实例。

而变量就只有一个,String s4[3]。

54305054554f8271ad367116762853ac.png

String s5 = new String("string");

那么很明显,s4 !=s5;

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

Stringa="ab"+"cd";

Stringb="abcd";

71dedd02e978f7654c9f8433059735a7.png

String a="ab"+"cd";

"ab"和"cd"分别创建了一个对象,它们经过“+”连接后又创建了一个对象"abcd",因此一共三个,并且它们都被保存在字符串池里了[5]。

那么你认为 String b="abcd";会如何呢?

6cf955154bd683fefa4550a2e44946cc.png

String b="abcd";

明白了吧。

参考网页:

[4] http://www.iteye.com/topic/774673 请别再拿“String s= new String("xyz");创建了多少个String实例”来面试了吧

时间:2017年5月26日22:28:35

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值