黑马程序员----------------Java基础-----------------String类

黑马程序员——Java基础——String类

——- android培训java培训、期待与您交流! ———-

String是我们经常用到的一个类型,其实有时候觉得写程序就是在反复的操作字符串,这是C的特点。在java中,jdk很好的封装了关于字符串的操作。这里主要总结三个类String、StringBuffer 、 StringBuilder。

这三个类基本上满足了我们在不同情景下使用字符串的需求。由于我们操作String的频率很高,它其中的方法不需要刻意地总结,用多了就会烂熟于心,熟能生巧!(其实是方法太多,自己整理不过来,呵呵……)

一. String

JDK的解释是 “Strings are constant; their values cannot be changed after they are created”也就是说String对象一旦被创建就是固定不变的了(你一定有问题,但请先等一等,耐心读下去),这样的一点好处就是可以多线程之间访问,因为只读不写。

一般情况下我们以下面两种方式创建一个String对象

String str1 = "String1";
String str2 = new String("String2");

两种方式是有区别的,这和java的内存管理有关,前面已经说过,string创建之后是不可变的,所以按照第一种方式创建的字符串会放在栈里,更确切的是常量池中,常量池就是用来保存在编译阶段确定好了大小的数据,一般我们定义的int等基本数据类型就保存在这里。

其具体的一个流程就是,编译器首先检查常量池,看看有没有一个“string”,如果没有则创建。如果有的话,则则直接把str1指向那个位置。

第二种创建字符串的方法是通过new关键字,还是java的内存分配,java会将new的对象放在堆中,这一部分对象是在运行时创建的对象。所以我们每一次new的时候,都会创建不同的对象,即便是堆中已经有了一个一模一样的。

练习一下

        String str1 = "string";  
        String str4 = "string";  
        String str2 = new String("string");  
        String str3 = new String("string");  

        /*用于测试两种创建字符串方式的区别*/ 
        System.out.println(str1 == str4);  
        System.out.println(str2 == str3);  
        System.out.println(str3 == str1);  

        str3 = str3.intern(); //一个不常见的方法  
        System.out.println(str3 == str1); 

结果
true //解释:两个字符串的内容完全相同,因而指向常量池中的同一个区域

false //解释:每一次new都会创建一个新的对象

false // 解释: 注意==比较的是地址,不仅仅是内容

true //介绍一下intern方法,这个方法会返回一个字符串在常量池中的一个地址,如果常量池中有与str3内容相同的string则返回那个地址,如果没有,则在常量池中创建一个string后再返回。实际上,str3现在指向了str1的地址。

这就是让人纠结的string了,现在你可以说话了。。。很多人有这样的疑问就是既然string是不变的,那么为什么str1 + “some”是合法的,其实,每次对string进行修改,都会创建一个新的对象。因此这里要注意的是要尽量避免反复对string进行修改,效率是很低的。

二.StringBuffer
  StringBuffer是一个线程安全的,就是多线程访问的可靠保证,最重要的是他是可变的,也就是说我们要操作一个经常变化的字符串,可以使用这个类,基本的方法就是append(与string的concat方法对应)和insert方法.
        StringBuilder sb = new StringBuilder("string builder");  
        StringBuffer sf = new StringBuffer("string buffer");  

        long start = System.currentTimeMillis();  

        for(int i = 0; i < 50000; i++)  
        {  
            //str1+= " ";  
            sb.append(" ");  
        }  

        long end = System.currentTimeMillis();  
        System.out.println("the run time is "+(end -start)+" ms"); 

测试一下,这次只需要8ms,这就是效率。

三.StringBuilder

那么接下来,就要问StringBuilder是干什么的,其实这个才是我们经常使用的,这个就是在jdk
1.5版本后面添加的新的类,前面说StringBuffer是线程同步的,那么很多情况下,我们只是使用一个线程,那个同步势必带来一个效率的问题,StringBuilder就是StringBuffer的非线程同步的版本,二者的方法差不多,只是一个线程安全(StringBuffer适用于多线程)一个没有线程安全(StringBuilder适用于单线程)。

接下来看看总结的效果。。。。。。(以下内容来自网络)

问题1:
String s1 = “abc”;
String s2 = “abc”;
System.out.println(s1 == s2);

这里的结果是true. 由于字符串是常量(内存中创建对象后不能修改), 而且字符串在程序中经常使用. 所以Java对其提供了缓冲区. 缓冲区内的字符串会被共享. 使用双引号的形式定义字符串常量就是存储在缓冲区中的. 使用”abc”时会先在缓冲区中查找是否存在此字符串, 没有就创建一个, 有则直接使用. 第一次使用”abc”时会在缓冲区中创建, 第二次则是直接引用之前创建好的了.

问题2:
String s1 = new String(“abc”);
String s2 = new String(“abc”);
System.out.println(s1 == s2);

这里的结果是false. 使用构造函数创建的字符串都是在缓冲区外面创建一个新的. 所以只要是使用构造函数创建的字符串, 和任何字符串都不会相等.

问题3:
String s1 = “abc”;
String s2 = “a”;
String s3 = “bc”;
String s4 = s2 + s3;
System.out.println(s1 == s4);

这里的结果是false. Java中字符串的相加其内部是使用StringBuilder类的append()方法和toString()方法来实现的. 而StringBuilder类toString()方法返回的字符串是通过构造函数创建的.

>问题4:
String s1 = “abc”;
String s2 = “a” + “bc”;
System.out.println(s1 == s2);

这里的结果是true. 其实这里的s2并没有进行字符串相加, 两个双引号形式的字符串常量相加, 在编译的时候直接会被转为一个字符串”abc”.

问题5:
String str = “abc”;
str.substring(3);
str.concat(“123″);
System.out.println(str);

这里结果是”abc”. 由于字符串是常量(内存中创建对象后不能修改), 该类中所有方法都不会改变字符串的值. 如果希望使用一个可变的字符串, 可以使用StringBuilder或StringBuffer类。

本文借鉴了
http://developer.51cto.com/art/201204/327109.htm
http://www.jfox.info/java-mian-shi-ti-zhong-chang-jian-de-guan-yu-string-lei-wen-ti-zong-jie

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值