java的String类型(二)浅谈JVM

在java虚拟机中大致分为了栈、堆、方法区、常量池以及本地方法区等,由于String的存储涉及一二,我们便来看一下一些简单的存储机理。

首先栈的存储特点:先进后出,用来存放顺序控制指令的基本数据类型,还有一些引用。值得我们注意的是(类里面的基本类型放在堆中,方法里面的基本类型在栈中),陆续我们都会讲到。

那么今天们要讲的String就主要存储在常量池中(现在的java认为常量池是堆的一部分)。

比如我们现在定义了两个String a和b。

即String a = “qwe”;

String b = “qw”;

那么我们就在栈中 有了a和b两个字符串的引用变量,在堆中的常量池中根据String的length给它分配足够的大空间(不可变性)。此时 “=”操作就会分别得到 “qwe”和“qw”的地址。也就是a指向了“qwe”,b指向了“qw”。

现在我们就可以清楚地看到我们的字符串的赋值操作了,那么问题来了,是不是我们每声明一个String变量在堆中都会有一个内存空间被申请呢?

String c = “qwe”;

现在 我们的java虚拟机得到这段代码后,会迅速在常量池中扫描搜索“qwe”,此前的 a 已经申请了这部分空间,所以我们的 c 会直接指向“qwe”,这就实现了字符串的共享。

如果我们重新又给了 c 一次赋值操作呢?

 c = “qwer”   

此时也就是c的指向发生了改变,它便指向了新的内存空间区域,它从“qwe”的指向转到了“qwer”的指向。也就是它获得了新的地址。值得我们注意的是,这次仅仅只是改变了c的指向,与a无关(即便它两是同一指向)。这也是java的值传递的一个样例。

String d = a+b;

 这个同样是根据a+b两个字符串拼接的length先分配足够大的空间,在常量池中有了一个“qweqw”的字符串,此时d指向了该字符串。

 c = c + “s”;

涉及到自身的拼接呢?并不是在c的指向那个字符串中直接+“s”,我们已经反复强调了不变性,一个字符串的地址确定了后就不可以修改了。这个我们会拿到原来c的地址和length来重新申请一个空间得到这个字符串“qwers”,c的指向也就发生了改变。而原来的“qwer”因为没有指向被清除(如果还有别的引用指向不会被清除)。

下面我们看一下String的比较方法

String s1 = “abc”;

String s2 = “abc”;

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

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

两个的输出结果都是“true”。但是两个的本质不同。“==”涉及到了指向问题,也就是两者如果是同一指向(记录了同一个地址),那么便是“true”,相反就是“false”。“equal()”是String类封装好的一个方法,用于比较字符串是否相等,不涉及指向问题。很简单相等就是相等。

String s3 = “abcd”;

String s4 = s3.substring(0,3);

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

System.out.println(s1.equals(s4));

前者的输出结果为“false”,s4是调用了s3的一个方法 截取了s3的部分字段,而这部分字符串由new一个新空间,s4指向了新空间(堆中并非常量池)。s1与s3的指向便不相同,所以为“false”。

后者为“true”,s1与s4代表的字段相同。

陆续会更新String的另一种构造方法,情况会有所不同。谢谢大家。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值