字符串的基础知识

字符串操作是计算机程序设计中最常见的行为。String对象是不可改变的,从JDK文档中可以看出,每一个对字符串进行修改的操作都会创建一个全新的对象,而原始对象仍然存在。以下是我对字符串基础知识的一些了解

重载"+"与StringBuilder


 

  1. 当用"+"拼接的都是字符串字面量和基本类型字面量时,该表达式等价于拼接后的字符串,以下两个表达式是等价的
    String str1 = "Hello" + " world" + 47;
    String str2 = "Hello world47";
  2. 若表达式中含有变量,如下
    String str = "";
    String s = str + "Hello" + "world";

    编译器会自动创建StringBuilder对象,并调用append方法对字符串拼接,最后调用toString方法创建字符串对象并返回String对象的引用赋值给s。可以通过javap -c class文件名命令来反编译.class文件,以下是输出结果的一部分

  3. 若遇到需要循环进行多次"+"操作时,如下
    String a = "a";
    for (int i = 0; i < 100000; i++)
          a += "a";

    这段代码的执行效率很低,因为循环一次就会创建一个StringBuilder对象并调用toString方法来创建String对象,所以执行过程中需要创建大量的对象。想要提高效率可以通过手动创建StringBuilder对象来对字符串进行拼接,如下

    StringBuilder sb = new StringBuilder("a");
    for (int i = 0; i < 100000; i++)
        sb.append("a");
    String s = sb.toString();
  4. 编码中可能会出现一些无意识的递归,如下
    class Test {
        public String toString() {
            return "Test: " + this;
        }
    }

    由于编译器看到字符串后面跟了一个"+",于是编译器会将this转为字符串即调用toString方法,以致于出现递归调用toString方法。若真想拼接上该对象的地址可以使用super.toString()来代替

String的一些常用API


  •  length:返回字符串的字符数量
    String s = "Hello world";
    int length = s.length();
    System.out.println(length); // 11
  • charAt:返回某个索引位置上的字符
    char c = s.charAt(6);  // s在上段代码中
    System.out.println(c); // w
  • getChars、getBytes:将字符串中的一串字符复制到指定数组中
    char[] cs = new char[5];
    s.getChars(0, 5, cs, 0);
    System.out.println(cs); // Hello
  • toCharArray:将字符串拆分成字符后存入char数组中
    char[] cs = s.toCharArray();
    System.out.println(cs); // Hello world
  • equals、equalsIgnoreCase:比较两个字符串的内容是否一致,后者忽略大小写
    System.out.println(s.equals("hello world")); // false
    System.out.println(s.equalsIgnoreCase("hello world")); // true
  • compareTo:通过每个字符对应的Unicode值来比较大小
    System.out.println(s.compareTo("Hello World")); //32
    System.out.println('w' - 'W'); // 32
  • contains:判断是否包含参数的内容
    System.out.println(s.contains("Hello")); // true
  • contentEquals:判断是否与参数的内容一致
    System.out.println(s.contentEquals("Hello")); // false
  • regionMatcher:判断该字符串中某段是否与参数字符串中的某段相同,有个忽略大小写的重载方法
    System.out.println(s.regionMatches(6, "world", 0, 5)); // true
  • startsWith、endsWith:判断是否以某个字符串开头、结尾
    System.out.println(s.startsWith("He")); // true
    System.out.println(s.endsWith("ld")); // true
  • indexOf、lastIndexOf:返回第一个、最后一个某个字符的索引位置,若没有返回-1
    System.out.println(s.indexOf('o')); // 4
    System.out.println(s.lastIndexOf('o')); // 7
    System.out.println(s.indexOf('h')); // -1
  • subString:截取字符串并返回截取出来的字符串
    System.out.println(s.substring(6)); // world
    System.out.println(s.substring(0, 5)); // Hello
  • concat:拼接字符串
    System.out.println(s.concat("!!!!")); // Hello world!!!!
  • replace:替换所有要替换的字符串为新的字符串,并返回替换后的字符串
    System.out.println(s.replace('l', 'L')); // HeLLo worLd
  • toLowerCase、toUpperCase:将字符串转为全大、小写
    System.out.println(s.toLowerCase()); // hello world
    System.out.println(s.toUpperCase()); // HELLO WORLD
  • trim:删除两端的空白字符,并返回删除后的字符
    String trim = "    Hello world    ".trim();
    System.out.println(trim); // Hello world
    System.out.println(trim.length()); // 11
  • intern:若字符串常量池中有该对象则返回常量池中对象的引用,若没有则直接返回该对象的引用,例子请看后面

字符串对象的存储位置


  1. 程序中字符串字面量的对象存储在常量池中
    String s = "Hello world";
  2. 通过new关键字创建的字符串对象存储在堆中
    String s = new String("Hello world");

    以上代码实际上是创建了两个对象,一个在常量池中一个在堆中,可以通过以下代码进行验证

    String s = new String("Hello world");
    System.out.println(s.intern() == s); // false

    由于常量池中存在该字符串对象,所以intern返回的是常量中的对象的引用,而s是堆中对象的引用,所以最终输出fals。但有的人错误的认为通过new创建出来的字符串就一定会有存在两个对象(可能只有我之前是这么认为的0.0),如下代码所示

    String str = new String(new char[]{'H', 'e', 'l', 'l', 'o'});
    System.out.println(str.intern() == str);  //true

     

 

posted @ 2017-07-26 09:40  回忆成长  阅读(337)  评论(0编辑  收藏  举报