Java中的String类用于字符串的创建以及有关字符串的一系列操作,程序中所有的双引号字符串都是String类的对象。字符串具有以下特点:

  • 字符串是不可变的
  • 字符串是可共享的
  • 字符串效果上相当于char[] 字符数组,但底层原理是byte[] 数组

1. 字符串的创建

字符串的创建主要包括四种方法:直接创建和三种构造方法

  • 直接创建:这也是使用最多的一种方法
  • 构造方法:

    • public String():创建一个空白字符串,不包含任何内容
    • public String(char[] array):根据字符数组的内容创建对应的字符串
    • public String(byte[] array):根据字节数组的内容创建字符串

      1. public class StringTest {
      2. public static void main(String[] args) {
      3. // 三种构造
      4. String str1 = new String();
      5. System.out.println(str1);
      6. char [] array = new char []{'k', 'o', 'b', 'e'};
      7. String str2 = new String(array);
      8. System.out.println(str2); // "kobe"
      9. byte[] bytearray = new byte[]{97, 98, 99};
      10. String str3 = new String(bytearray); // "kobe"
      11. System.out.println(str3);
      12. // 直接创建
      13. String str4 = "kobe";
      14. System.out.println(str4); // "kobe"
      15. }
      16. }

2. 字符串常量池

程序中直接写上双引号的字符串都在字符串常量池中,那么它们和使用构造方法创建的字符串有什么不同呢?首先通过一个例子直观的看一下:

  1. public class StringTest1 {
  2. public static void main(String[] args) {
  3. String str1 = "abc";
  4. String str2 = "abc";
  5. char[] chararray = new char[]{'a', 'b', 'c'};
  6. String str3 = new String(chararray);
  7. System.out.println(str3);
  8. System.out.println(str1 == str2); // true
  9. System.out.println(str1 == str3); // false
  10. System.out.println(str2 == str3); // false
  11. }
  12. }

如上所示,str1和str2是通过双引号直接创建的,str3是通过构造方法创建。然后我们使用 == 来比较它们发现,str1和str2是相同的,但它们与str3都是不同的。表面上看起来它们都创建了字符串”abc”,为什么会出现这种情况呢?这是因为通过双引号直接创建的字符串都在堆内存的字符串常量池中,而通过构造方法创建的字符串在堆中。而且对于基本类型来说, == 是进行数值的比较,而对于引用类型来说是进行地址值的比较。下面我们通过内存空间来看一下为什么会有这种现象。
String内存图.png

代码如上所示,接下来我们按照代码的执行过程依次看以下内存空间是如何变化的:

  • str1和str2是通过双引号直接创建的,因此它们保存的都是”abc”在堆内存的字符串常量池中的地址,假设为0x233
  • 接着创建一个一个char型数组,数组内容为[‘a’, ‘b’, ‘c’],它保存在堆中
  • 然后通过构造方法创建一个String对象,它通过保存在堆中,同时假设它在堆中的地址为0x666,因此栈中str3保存的就是对象的地址0x666。但底层仍然是一个byte[]

由上可知,由于str1和str2指向的是字符串常量池中同样的内容,因此地址相同,==的结果为true。而str3是new的一个新的String对象,它保存在堆的其他位置而不是在字符串常量池中,因此地址不同,== 的结果为false。


由上面的分析知道,==进行的是地址值的比较。如果想要进行字符串内容的比较,可以使用以下两个方法:

  • public boolean equals(Object obj): 参数可以是任何对象,只有参数是一个字符串并且内容相同时返回true,否则返回false
    1. 任何对象都能用Object接收
    2. equals方法具有对称性,即a.equals(b) b.equals(a) 效果一样
    3. 如果比较一个常量和一个变量,推荐使用 常量.equals(变量)的写法
  • public boolean equalsIgnoreCase(String str): 忽略大小写,进行内容比较
  1. public class StringTest2 {
  2. public static void main(String[] args) {
  3. String str1 = "abc";
  4. String str2 = "abc";
  5. char[] chararray = new char[]{'a', 'b', 'c'};
  6. String str3 = new String(chararray);
  7. System.out.println(str1.equals(str2)); // true
  8. System.out.println(str1.equals(str3)); // true
  9. System.out.println(str3.equals("abc")); // true
  10. System.out.println("abc".equals(str1)); // true
  11. String strA = "Java";
  12. String strB = "java";
  13. System.out.println(strA.equals(strB)); // false
  14. System.out.println(strA.equalsIgnoreCase(strB)); // true
  15. }
  16. }

3. String中和获取相关的方法:

  • public int length(): 获取字符串中含有的字符个数
  • public String concat(String str): 将当前字符串和参数字符串拼接为新字符串返回,当然同样可以通过 + 实现字符串拼接
  • public char charAt(int index): 获取指定索引位置的单个字符
  • public int indexOf(String str): 查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回-1
  1. public class StringGetTest {
  2. public static void main(String[] args) {
  3. String str = "abc";
  4. System.out.println(str.length()); // 3
  5. String str1 = "hello";
  6. String str2 = "world";
  7. String str3 = str1.concat(str2);
  8. System.out.println(str1); // hello
  9. System.out.println(str2); // world
  10. System.out.println(str3); // helloworld
  11. System.out.println(str.charAt(0)); // a
  12. System.out.println(str.indexOf("bc")); // 1
  13. System.out.println(str.indexOf("ff")); // -1
  14. }
  15. }

4. 字符串的截取方法:

  • public String subString(int index):截取从参数位置一直到字符串末尾,返回新字符串
  • public String subString(int begin, int end): 截取[begin, end)范围内的字符串
  1. public class SubStringTest {
  2. public static void main(String[] args) {
  3. String str = "hello world";
  4. String str2 = str.substring(2);
  5. System.out.println(str2); // llo world
  6. System.out.println(str.substring(2, str.length() - 2)); // llo wor
  7. // strA 中保存的是地址值
  8. // 为strA 赋予不同的字符串是改变了strA中保存的地址值,但"hello"和"world"是不可改变的
  9. String strA = "hello";
  10. System.out.println(strA); // hello
  11. strA = "world";
  12. System.out.println(strA); // world
  13. }
  14. }

5. 字符串转换相关方法

  • public char[] toCharArray(): 将当前字符串拆分为字符数组返回
  • public byte[] getBytes(): 获取当前字符串底层的字节数组
  • public String replace(charSequence oldString, CharSequence newString): 将所有出现的老字符串替换成新的字符串,返回替换之后的结果
  1. public class StringConvertTest {
  2. public static void main(String[] args) {
  3. String str = "helloworld";
  4. char [] charArray = str.toCharArray();
  5. System.out.println(charArray); // helloworld
  6. System.out.println(Arrays.toString(charArray)); // [h, e, l, l, o, w, o, r, l, d]
  7. System.out.println(charArray.length); // 10
  8. byte [] byteArray = str.getBytes();
  9. System.out.println(byteArray[3]); // 108
  10. String str1 = "Fologen love Kobe";
  11. String str2 = str1.replace("o", "*");
  12. System.out.println(str1); // Fologen love Kobe
  13. System.out.println(str2); // F*l*gen l*ve K*be
  14. }
  15. }

6. 字符串分割方法

  • public Sting[] split(String regex):按照参数的规则,将字符串切分成若干部分,其中regex为正则表达式
  1. public class StringSplitTest {
  2. public static void main(String[] args) {
  3. String str = "aaa,bbb,ccc";
  4. String [] array = str.split(",");
  5. for (int i = 0; i < array.length; i++) {
  6. System.out.println(array[i]); // aaa bbb ccc
  7. }
  8. }
  9. }

7. 更多

Java String 类 Class String