String与常量池

这两天想着巩固一下基础,昨天突然想起来之前学数据类型这一块,String类型是特殊的引用类型,想看看特殊在何处,然后自己写了个入口,测了一下下面的代码:

String a = "123";
String b = "123";
String c = a;
System.out.println(String.valueOf(a==b)+"--"+String.valueOf(a==c)+"--"+String.valueOf(b==c));
a = "1234";
System.out.println(String.valueOf(a==b)+"--"+String.valueOf(a==c)+"--"+String.valueOf(b==c));

为什么会这么测呢,因为我记得String是引用数据类型嘛,心里感觉像这种String c = a;
会使c与a指向同一个堆内存,这样c永远是==a的,不过结果却跟我想的不一样:
这里写图片描述
额。。难道因为我没有new对象吗,再试试:

String d = new String("123");
String e = d;
System.out.println(d==e);
d = "1234";
System.out.println(d==e);

这样的话,d会指向我new出的对象在堆里的地址了吧,e和d会引用同一个对象了吧,我再执行:
这里写图片描述
这我就有点懵了,赶紧去找资料,看原理,发现还有常量池概念:

Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。
所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。
而运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。
第一段代码中,“123”,“1234”都会放在常量池中,然后a,b,c先指向“123”,之后a指向了“1234”,所以呢,第二个输出结果中,a是与其他两个变量不等的。
第二段代码中,“1234”是放在常量池的,new String("123");放在堆中,而且一开始d和e同时指向了堆中的string对象,之后d又指向了常量池中的“1234”,这样就导致d和e不等了。
有一段代码段是很好的例子,我引用一下:

        String s1 = "Hello";
        String s2 = "Hello";
        String s3 = "Hel" + "lo";
        String s4 = "Hel" + new String("lo");
        String s5 = new String("Hello");
        String s6 = s5.intern();
        String s7 = "H";
        String s8 = "ello";
        String s9 = s7 + s8;
        System.out.println(s1 == s2);  // true
        System.out.println(s1 == s3);  // true
        System.out.println(s1 == s4);  // false
        System.out.println(s1 == s9);  // false
        System.out.println(s4 == s5);  // false
        System.out.println(s1 == s6);  // true

s3这里,编译器会直接拼成”Hello”,所以说s1,s2,s3都是指向常量池中的”Hello”;
s7,s8分别又指向常量池中的“H”和“ello”;
然后s4这里呢,是常量池中的“Hel”与堆中的string对象new String(“lo”)拼接后的string对象放到了堆中,s4指向拼接后的对象;
s5直接指向堆中的new String(“Hello”)对象;
s6这里呢跟s5有关,s5在堆中,内容为Hello ,intern方法会尝试将Hello字符串添加到常量池中,并返回其在常量池中的地址,因为常量池中已经有了Hello字符串,所以intern方法直接返回地址;
最后s9,是由两个变量来赋值出来的,s9在编译的时候,编译器并不知道s7和s8具体是啥,所以呢s9是指向堆中s7对象和s8对象的拼接。
然后联想到一个东西:

String a = "1"+"2"+"3";

String是不可变的,加号的拼接作用,其实会在常量池中,先有”1”,再有”12”,再有”123”,产生了临时变量,造成效率低下。而StringBuffer是可变的。
博文参考:http://blog.csdn.net/qq_27093465/article/details/52033327
里面还有更详细的内容,关于class文件的常量池,暂且不谈。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值