Java你所不知道的细节——String、StringBuffer、StringBuilder(1)

这个可能是Java里面一个老掉牙的细节了,不过我还是要说,还是有你不知道的地方
本文参考博客Java之美http://blog.csdn.net/zhangerqing/article/details/8093919

  1. String的用法注意

(1)String s = “123” + “456"内存中产生几个字符串对象?
这是个比较有争议的问题,面试的时候,老师还挺喜欢问,论坛上大家说几个的也有,我给大家分析一下,因为我们前面有提到Java字符串的缓存机制,编译器在编译的时候会进行优化,所以在编译的过程中123和456被合成了一个字符串"123456”,因此,如果缓存池中目前没有123456这个对象,那么会产生一个,即"“123456”,且栈中产生一个引用s指向它,如果缓存池中已经存在"123456",那么将产生0个对象,直接用s指向它。

(2)如果spilt()函数的参数在要分割的字符串中没有怎么办?如String s = “helloworld” ,我现在调用String[] s2 = s.spilt(“abc”),返回什么?
像这样的题目,如果不亲自遇到过,或者看过源代码,很难准确的写出来。

做一个简单的测试,就可以看得出来:

package com.xtfggef.string;  
  
public class StringSpilt {  
    public static void main(String[] args) {  
        String s = "helloworld";  
        String[] s2 = s.split("abc");  
        for (int i = 0; i < s2.length; i++) {  
            System.out.println(s2[i] + " " + i);  
        }  
    }  
}  

输出:helloworld 0

说明当遇到源字符串中没有的字符时,会把它整个串放入到数组中。spilt()的内部实现还是挺复杂的,多层嵌套,不便于放到这儿分析。

(3)关于字符串自动类型转换分析

首先看一下题的类型:

int i = 2;  
int j = 3;  
String s = "9";  
System.out.println(i+j+s);        
System.out.println("-----------------------");  
System.out.println(i+s+j);

以上运算各输出什么?不妨猜猜
59


293

首先i+j=5,然后5和9自然连接,这里涉及到java的自动类型转换,此处int型的直接转成String类型的。第二个依次连接,都转化为String类型的了。

补充(细节):看下面的程序:

String s = "ab";
String s1 = "a";
String s2 = s1 + "b";
String s3 = "ab"; 
System.out.println(s == s2);//false
System.out.println(s2 == s3);//false
System.out.println(s2.hashCode() == s3.hashCode());
String s4 = "ad";
String s5 = "a" + "d";
String s6 = "ad";
System.out.println(s4 == s5);//true
System.out.println(s4 == s6);//true

此处主要是想说明:s1+“b"和"a”+"b"的不同,再看一段代码:

System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());
System.out.println(s5.hashCode());

输出:

97
3105
3105
3107
3107

说明s1+"b"的过程创建了新的对象,所以地址不一样了。所以用==比较的话,返回的是false。

2.StringBuffer、StringBuilder和String的区别

二者几乎没什么区别,基本都是在调用父类的各个方法,一个重要的区别就是StringBuffer是线程安全的,内部的大多数方法前面都有关键字synchronized,这样就会有一定的性能消耗,StringBuilder是非线程安全的,所以效率要高些。

StringBuffer sb = new StringBuffer("hello");
StringBuffer sb2 = new StringBuffer("hello");
System.out.println(sb.equals(sb2));

以上程序输出false,是不是有点惊讶?equals()比较的是字符串的内容,按理说此处应该输出的是true才对。
究其原因,String类重写了Object的equals(),所以只需要看内容是否相等即可,但是StringBuffer没有重写equals(),此处的equals()仍然是调用的Object类的,所以,调用StringBuffer类的equals(),只有地址和内容都相等的字符串,结果才会返回true。

另外StringBuffer有一系列追加、插入、删除字符串的方法,首先append(),就是在原来的字符串后面直接追加一个新的串,和String类相比有明显的好处:

String类在追加的时候,源字符串不变(这就是为什么说String是不可变的字符串类型),和新串连接后,重新开辟一个内存。这样就会造成每次连接一个新串后,都会让之前的串报废,因此也造成了不可避免的内存泄露。

我的GitHub
QQ:2541692705
邮箱:loyalwilliams@163.com
我想去流浪,我想去读书,若有机会,江湖再见
扫一扫,领取红包,就当奖励你我付出的努力

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值