zoukankan      html  css  js  c++  java
  • java中字符串的用法

    1、String中的每个字符都是一个16位的Unicode字符,用Unicode很容易表达丰富的国际化字符集,比如很好的中文支持。甚至Java的标识符都可以用汉字,但是没人会用吧(只在一本清华的《Java2实用教程》看过)。

    2、判断空字符串。根据需要自己选择某个或者它们的组合
        if ( s == null )    //从引用的角度
        if ( s.length() == 0 )     //从长度判别
        if ( s.trim().length () == 0 )     //是否有多个空白字符
    trim()方法的作用是是移除前导和尾部的Unicode值小于'"u0020'的字符,并返回“修剪”好的字符串。这种方法很常用,比如需要用户输入用户名,用户不小心加了前导或者尾部空格,一个好的程序应该知道用户不是故意的,即使是故意的也应该智能点地处理。
    判断空串是很常用的操作,但是Java类库直到1.6才提供了isEmpty()方法。当且仅当 length() 为 0 时返回 true。

    3、未初始化、空串""与null。它们是不同的概念。对未初始化的对象操作会被编译器挡在门外;null是一个特殊的初始化值,是一个不指向任何对象的引用,对引用为null的对象操作会在运行时抛出异常NullPointerException;而空串是长度为0的字符串,和别的字符串的唯一区别就是长度为0。
    例子:
        public class StringTest{
            static String s1;
            public static void main(String[] args) {
                String s2;
                String s3 = "";
                System.out.print(s1.isEmpty());     //运行时异常
                System.out.print(s2.isEmpty());     //编译出错
                System.out.print(s3.isEmpty());     //ok!输出true
            }
        }

    4、String类的方法很多,在编写相关代码的时候看看JDK文档时有好处的,要不然花了大量时间实现一个已经存在的方法是很不值得的,因为编写、测试、维护自己的代码使项目的成本增加,利润减少,严重的话会导致开不出工资……

    5、字符串的比较。
    Java不允许自定义操作符重载,因此字符串的比较要用compareTo() 或者 compareToIgnoreCase()。s1.compareTo(s2),返回值大于0则,则前者大;等于0,一般大;小于0,后者大。比较的依据是字符串中各个字符的Unicode值。

    6、toString()方法。
    Java的任何对象都有toString()方法,是从Object对象继承而来的。它的作用就是让对象在输出时看起来更有意义,而不是奇怪的对象的内存地址。对测试也是很有帮助的。

    7、String对象是不变的!可以变化的是String对象的引用。
    String name = "ray";
    name.concat("long");  //字符串连接
    System.out.println(name); //输出name,ok,还是"ray"
    name = name.concat("long");  //把字符串对象连接的结果赋给了name引用
    System.out.println(name);  //输出name,oh!,变成了"raylong"
    上述三条语句其实产生了3个String对象,"ray","long","raylong"。第2条语句确实产生了"raylong"字符串,但是没有指定把该字符串的引用赋给谁,因此没有改变name引用。第3条语句根据不变性,并没有改变"ray",JVM创建了一个新的对象,把"ray","long"的连接赋给了name引用,因此引用变了,但是原对象没变。

    8、String的不变性的机制显然会在String常量内有大量的冗余。如:"1" + "2" + "3" +......+ "n" 产生了n+(n+1)个String对象!因此Java为了更有效地使用内存,JVM留出一块特殊的内存区域,被称为“String常量池”。对String多么照顾啊!当编译器遇见String常量的时候,它检查该池内是否已经存在相同的String常量。如果找到,就把新常量的引用指向现有的String,不创建任何新的String常量对象。

    那么就可能出现多个引用指向同一个String常量,会不会有别名的危险呢?No problem!String对象的不变性可以保证不会出现别名问题!这是String对象与普通对象的一点区别。

    乍看起来这是底层的机制,对我们编程没什么影响。而且这种机制会大幅度提高String的效率,实际上却不是这样。为连接n个字符串使用字符串连接操作时,要消耗的时间是n的平方级!因为每两个字符串连接,它们的内容都要被复制。因此在处理大量的字符串连接时,而且要求性能时,我们不要用String,StringBuffer是更好的选择。

    8、StringBuffer类。StringBuffer类是可变的,不会在字符串常量池中,而是在堆中,不会留下一大堆无用的对象。而且它可将字符串缓冲区安全地用于多个线程。每个StringBuffer对象都有一定的容量。只要StringBuffer对象所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。这个固定的容量是16个字符。我给这种算法起个名字叫“添饭算法”。先给你一满碗饭,不够了再给你一满碗饭。
    例子:
        StringBuffer sb = new StringBuffer();    //初始容量为 16 个字符
        sb.append("1234");    //这是4个字符,那么16个字符的容量就足够了,没有溢出
        System.out.println(sb.length());    //输出字符串长度是4
        System.out.println(sb.capacity());    //输出该字符串缓冲区的容量是16

        sb.append("12345678901234567");        //这是17个字符,16个字符的容量不够了,扩容为17+16个字符的容量
        System.out.println(sb.length());    //输出字符串长度是17
        System.out.println(sb.capacity());    //输出该字符串缓冲区的容量是34

        sb.append("890").reverse().insert(10,"-");   
        System.out.println(sb);        //输出0987654321-09876543214321

    字符串的长度和字符缓冲区的容量是两个概念,注意区别。
    还有串联的方式看起来是不是很酷!用返回值连接起来可以实现这种简洁和优雅。

    10、StringBuilder类。 从J2SE 5.0 提供了StringBuilder类,它和StringBuffer类是孪生兄弟,很像。它存在的价值在于:对字符串操作的效率更高。不足的是线程安全无法保证,不保证同步。那么两者性能到底差多少呢?很多!
    请参阅:http://book.csdn.net/bookfiles/135/1001354628.shtml
    实践:
    单个线程的时候使用StringBuilder类,以提高效率,而且它的API和StringBuffer兼容,不需要额外的学习成本,物美价廉。多线程时使用StringBuffer,以保证安全。

    11、字符串的比较。
    下面这条可能会让你晕,所以你可以选择看或者不看。它不会对你的职业生涯造成任何影响。而且谨记一条,比较字符串要用equals()就ok了!一旦用了“==”就会出现很怪异的现象。之所以把这部分放在最后,是想节省大家的时间,因为这条又臭又长。推荐三种人:一、没事闲着型。二、想深入地理解Java的字符串,即使明明知道学了也没用。三、和我一样爱好研究“茴”字有几种写法。

    还是那句老话,String太特殊了,以至于某些规则对String不起作用。个人感觉这种特殊性并不好。看例子:
    例子A:
        String str1 = "java";
        String str2 = "java";
        System.out.print(str1==str2);
    地球上有点Java基础的人都知道会输出false,因为==比较的是引用,equals比较的是内容。不是我忽悠大家,你们可以在自己的机子上运行一下,结果是true!原因很简单,String对象被放进常量池里了,再次出现“java”字符串的时候,JVM很兴奋地把str2的引用也指向了“java”对象,它认为自己节省了内存开销。不难理解吧 呵呵
    例子B:
        String str1 = new String("java");
        String str2 = new String("java");
        System.out.print(str1==str2);
    看过上例的都学聪明了,这次肯定会输出true!很不幸,JVM并没有这么做,结果是false。原因很简单,例子A中那种声明的方式确实是在String常量池创建“java”对象,但是一旦看到new关键字,JVM会在堆中为String分配空间。两者声明方式貌合神离,这也是我把“如何创建字符串对象”放到后面来讲的原因。大家要沉住气,还有一个例子。
    例子C:
        String str1 = "java";
        String str2 = "blog";
        String s = str1+str2;
        System.out.print(s=="javablog");
    再看这个例子,很多同志不敢妄言是true还是false了吧。爱玩脑筋急转弯的人会说是false吧……恭喜你,你会抢答了!把那个“吧”字去掉你就完全正确。原因很简单,JVM确实会对型如String str1 = "java"; 的String对象放在字符串常量池里,但是它是在编译时刻那么做的,而String s = str1+str2; 是在运行时刻才能知道(我们当然一眼就看穿了,可是Java必须在运行时才知道的,人脑和电脑的结构不同),也就是说str1+str2是在堆里创建的,s引用当然不可能指向字符串常量池里的对象。没崩溃的人继续看例子D。
    例子D:
        String s1 = "java";
        String s2 = new String("java");
        System.out.print(s1.intern()==s2.intern());
    intern()是什么东东?反正结果是true。如果没用过这个方法,而且训练有素的程序员会去看JDK文档了。简单点说就是用intern()方法就可以用“==”比较字符串的内容了。在我看到intern()方法到底有什么用之前,我认为它太多余了。其实我写的这一条也很多余,intern()方法还存在诸多的问题,如效率、实现上的不统一……
    例子E:
        String str1 = "java";
        String str2 = new String("java");
        System.out.print(str1.equals(str2));
    无论在常量池还是堆中的对象,用equals()方法比较的就是内容,就这么简单

  • 相关阅读:
    mysql报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    MD5登陆密码的生成
    15. 3Sum、16. 3Sum Closest和18. 4Sum
    11. Container With Most Water
    8. String to Integer (atoi)
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    几种非线性激活函数介绍
    AI初探1
    AI初探
  • 原文地址:https://www.cnblogs.com/ilxx1988/p/2939726.html
Copyright © 2011-2022 走看看