String 类 在java中是非常特殊的,而且也是经常使用的,本文所讲的是String类要熟知的知识点

1. String 并不是以 \0 结束的

  • 并不像 c/c++ 那样,string 是以 \0 结尾的,java 中String是对象存储的,底层数据存储在 char[]中,你可以使用 charToArray来获得String 的char array

2. String 在 java中 是 f不可变的并且是 inal class

  • String是不可变的,意味着对象一旦创建你就不可以改变其值[重新赋值实际上是重新创建新的对象]。像toLowerCase, toUpperCase 这类操作都会返回一个新的对象。
  • String 的返回是不能被重写的
  • 对于为什么 String 会被定义为 final class 或是 不可变的,可以点击链接阅读

3. String字符串是存储在 字符串池中的

  • 字符串常量(eg: “walterblog”)是存储在一块独立的内存的,字符串池.每次你使用 字符串常量来初始化String 对象时, JVM 都会去 String Pool 检查是否有相同的字符串常量,有则返回没有则创建新的内存并放入字符串池。如果使用 new String 来创建对象的话,JVM不会检查 String Pool 的。

  • 以下代码可以更好的理解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    String name = "Scala"; //1st String object
    String name_1 = "Scala"; //same object referenced by name variable
    String name_2 = new String("Scala"); //different String object

    //this will return true
    if(name==name_1){
    System.out.println("both name and name_1 is pointing to same string object");
    }

    //this will return false
    if(name==name_2){
    System.out.println("both name and name_2 is pointing to same string object");
    }
    // output
    both name and name_1 is pointing to same string object
  • 当然你可以使 new String 创建的对象放入到 String Pool中,使用 java.lang.String.inter() 方法可以实现

    1
    2
    3
    4
    5
    String A = new String("abc").intern();
    String B = "abc";
    System.out.println(A == B);
    // output
    true

4. 使用 equals 函数来比较两个String object

  • String 中的equals 是重写Object类的,是比较对象的内容是否相等,和字符大小写,顺序相关的。

5. 使用indexof, lastIndexof, matchs, startsWith, endsWith查询字符子串,或者匹配字符串

  • indexof, lastIndexof当不存在子串时,返回 -1
  • matchs是使用正则表达式来匹配字符串的,Pattern 类 更加强大
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    String str = "Java is best programming language";

    if(str.indexOf("Java") != -1){
    System.out.println("String contains Java at index :" + str.indexOf("Java"));
    }

    // J.* 表示字符串必须以 J 开头,而 J* 则表示字符串不一定是以J开头的
    if(str.matches("J.*")){
    System.out.println("String Starts with J");
    }

    str ="Do you like Java ME or Java EE";

    if(str.lastIndexOf("Java") != -1){
    System.out.println("String contains Java lastly at: " + str.lastIndexOf("Java"));
    }

6. 使用substring 获得原字符串的子串

7. 使用 + 运算符来连接字符串

8. 使用 trim() 函数来去除字符串的首尾的空白字符

  • String 提供 trim() 方法来去除字符串的首尾空白字符,如果没有,则返回原来的字符串,否则返回新的字符串。
  • 除了trim(),还有 replace(), replaceAll()来替换原有字符换的某些子字符串,同样可以使用正则表达式, replaceAll(‘ ‘, ‘’), 可以用来去除字符串中所有的空白字符
1
2
String a = " df ff  ";
String b = a.trim(); //b = "df ff"

9.split String 指定split 字符串分割字符串,可以使用正则表达式

  • 指定 分割字符串 将String 分割成 String 数组
    1
    2
    String a = "a,b,c,d";
    String[] b = a.split(",");

10.不要将重要的数据(比如密码)存储在String 中

11. equals 使用

  • 使用 equals 时 最好如下使用
    1
    2
    String a;
    "abc".equals(a); //这样a 如果 null 则不会抛出 NullPointExeption 异常,更加健壮

12. StringBuffer vs StringBuilder

  • StringBuffer 是线程安全和可变的
  • StringBuilder 是线程不安全和可变

13. String 为什么是不可变的

  • String 类型非常常用的,比如数据库连接url,文件名等,若是可变的话,则如果在外部更改,则会变的很不安全
  • 在多线程环境下,String 的不可变特性对于多线程共享变量非常有用
  • HashMap等关联性容器,用String作key非常常见,如果String是可变的话,则key插入前的hashCode 是一个值在插入后,String值变了,则hashCode 的值又是另一个了,这样每一次获取value时,hashCode都会重新计算。如果是不可变的,则可以缓存hashCode的值,只计算一次,这样可以加快元素的访问速度
  • 当然还有其他原因 -_-

14. 使用 System.out.printf 代替 System.out.println

  • System.out.printf 可以格式字符串,用法类似C 语言中的 printf
    1
    System.out.printf("%s-%06d", "Hello", "2015");

留言