《String类》

时间:2024-11-30 13:12:49

目录

一、定义与概述

二、创建字符串对象

2.1 直接赋值

2.2 使用构造函数

三、字符串的不可变性

四、常用方法

4.1 String对象的比较

4.1.1 ==比较是否引用同一个对象

4.1.2 boolean equals(Object anObject)方法:按照字典序比较

4.1.3 int compareTo(String s)方法: 按照字典序进行比较

4.1.4 int compareToIgnoreCase(String str)方法:

4.2 字符串查找

4.2 转化

4.3 字符串替换

4.4 字符串拆分

4.5 字符串截取

4.6 其他操作

五、StringBuilder和StringBuffer


一、定义与概述

在Java中,Sting类是用来表示字符串的。字符串是一个字符序列,例如"Hello, World! "。String类位于 java.lang 包中,这个包是Java语言的核心包之一,不需要显示导入就可以使用。

二、创建字符串对象

2.1 直接赋值

可以通过直接使用双引号来创建String对象,例如:String str = "Hello, World! " 。这种方式创建的字符串,在 Java 的字符串常量池中会检查是否已经存在相同内容的字符串。如果存在,就直接引用该字符串对象;如果不存在,则在常量池中创建一个新的字符串对象。

代码如下:

  

public class Test1 {
    public static void main(String[] args) {
        String str = "Hello, World! ";
    }
}

2.2 使用构造函数

String():创建一个空字符串对象。例如:String str1 = new String();

String(String original): 使用另一个字符串来创建新的字符串对象。String str2 = new String("Another Java String");

String(char[] value): 通过字符数组来创建字符串,例如:char[] chars = {'h','e','l','l','o'};
String str3 = new String(chars); 这里str3的值就是"hello"。

上述代码:

public class Test1 {
    public static void main(String[] args) {
        String str = "Hello, World! ";
        String str1 = new String();
        String str2 = new String("Another Java String");
        char[] chars = {'h','e','l','l','o'};
        String str3 = new String(chars);
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);
    }

输出:

三、字符串的不可变性

String类是不可变的(immutable)。这意味着一旦一个String对象被创建,它的值就不能被改变。例如:

String str = "Java";
str = str + " is fun";

在这个例子中,看起来好像是改变了 str 的值,但实际上并不是。当执行 str = str + " is fun"这一行时,会创建一个新的 String 对象,其内容是 "Java is fun",然后 str 变量会指向这个新创建的对象,原来的 "Java" 字符串对象仍然存在于内存中(如果没有其他引用指向它,它会在适当的时候被垃圾回收)。

String类在设计时就是不可改变的,String类实现描述中已经说明了

1. String类被final修饰,表明该类不能被继承

2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。

四、常用方法

4.1 String对象的比较

4.1.1 ==比较是否引用同一个对象

注意:对于内置类型,==比较的是变量中的值;对于引用类型==比较的是引用中的地址。

public class Test2 {
    public static void main(String[] args) {
        int a=100;
        int b=200;
        int c=200;
        // 对于基本类型变量,==比较两个变量中存储的值是否相同
        System.out.println(a == b); //false
        System.out.println(b == c); //true
        
        System.out.println("===========");
        // 对于引用类型变量,==比较两个引用变量引用的是否为同一个对象
        String s1 = new String("hello");
        String s2 = new String("hello");
        String s3 = new String("world");
        String s4 = s1;
        System.out.println(s1 == s2);   // false
        System.out.println(s2 == s3);   // false
        System.out.println(s1 == s4);   // true
    }
}

输出:

如果写成下面的形式,会输出true。因为s5 创建后 hello会被放入字符串常量池,就会认为s5 和s6引用的时同一对象。

        String s5 = "hello";
        String s6 = "hello";
        System.out.println(s5 == s6);

4.1.2 boolean equals(Object anObject)方法:按照字典序比较

String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后。

下面是String类重写equals方法的实现规则

public class Test3 {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");
        String s3 = new String("Hello");
        System.out.println(s1.equals(s2));//true
        System.out.println(s2.equals(s3));//false
    }
}

输出截图:

equals比较:String对象中的逐个字符。虽然s1与s2引用的不是同一个对象,但是两个对象中放置的内容相同,因此输出true 。s1与s3引用的不是同一个对象,而且两个对象中内容也不同,因此输出false。

4.1.3 int compareTo(String s)方法: 按照字典序进行比较

与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:

1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值。

2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值。

public class Test4 {
    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("ac");
        String s3 = new String("abc");
        String s4 = new String("abcdef");
        System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1
        System.out.println(s1.compareTo(s3)); // 相同输出 0
        System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
    }
}

输出截图:

4.1.4 int compareToIgnoreCase(String str)方法:

与compareTo方式形同,但是忽略大小写。

public class Test5 {
    public static void main(String[] args) {
        String s1 = new String("abC");
        String s2 = new String("Ac");
        String s3 = new String("Abc");
        String s4 = new String("ABcdef");
        System.out.println(s1.compareToIgnoreCase(s2));
        System.out.println(s1.compareToIgnoreCase(s3));
        System.out.println(s1.compareToIgnoreCase(s4));
    }
}

输出截图:

4.2 字符串查找

方法 功能
char charAt(int index) 返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常。
int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1
int indexOf(int ch, int fromIndex) 从fromIndex位置开始找ch第一次出现的位置,没有返回-1
int indexOf(String str) 返回str第一次出现的位置,没有返回-1
int indexOf(String str, int fromIndex) 从fromIndex位置开始找str第一次出现的位置,没有返回-1
int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置,没有返回-1
int lastIndexOf(int ch, int fromIndex) 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返 回-1
int lastIndexOf(String str) 从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str, int fromIndex) 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返 回-1

public class Test6 {
    public static void main(String[] args) {
        String s = "abccbaabccba";
        System.out.println(s.charAt(2)); // 'c'
        System.out.println(s.indexOf('c'));// 2
        System.out.println(s.indexOf('a',2));// 5
        System.out.println(s.indexOf("aa"));// 5
        System.out.println(s.indexOf("cc",4));//8
        System.out.println(s.lastIndexOf('c'));//9
        System.out.println(s.lastIndexOf('b',11));//10
        System.out.println(s.lastIndexOf("aa"));//5
        System.out.println(s.lastIndexOf("aa",4));//-1
    }
}

运行截图:

4.2 转化

1. 数值和字符串转化

class Student{
    public String name;
    public int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "name=" + name +  ", age=" + age ;
    }
}
public class Test7 {
    public static void main(String[] args) {
        //其它类型转化成字符串
        String s1 = String.valueOf(1000);
        String s2 = String.valueOf('a');
        String s3 = String.valueOf(12.34);
        String s4 = String.valueOf(new Student("zhangsan",13));
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
        //字符串转化数字
        int data1 = Integer.parseInt("1234");
        double data2 = Double.parseDouble("12.34");
        System.out.println(data1);
        System.out.println(data2);
    }
}

运行截图:

2. 大小写转换

public class Test8 {
    public static void main(String[] args) {
        String s1 = "abc";
        //小写转换大写
        System.out.println(s1.toUpperCase());
        String s2 = "ABC";
        //大写转换小写
        System.out.println(s2.toLowerCase());
    }
}

运行截图:

3. 字符串转数组

public class Test9 {
    public static void main(String[] args) {
        String s = "hello";
        //字符串转化数组
        char[] chars = s.toCharArray();
        for (char ch : chars) {
            System.out.print(ch + " ");
        }
        System.out.println();
        //数组转换字符串
        char[] chars1 = {'w','o','r','l','d'};
        String s1 = new String(chars1);
        System.out.println(s1);
    }
}

运行截图:

4. 格式化

public class Test9 {
    public static void main(String[] args) {
        String s = String.format("%d-%d-%d",2024,11,29);
        System.out.println(s);
    }
}

运行截图:

4.3 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:

方法 功能
String replaceAll(String regex, String replacement) 替换所有的指定内容
String replaceFirst(String regex, String replacement) 替换首个内容
public class Test9 {
    public static void main(String[] args) {
        String s = "abccba";
        System.out.println(s.replaceAll("c", "_"));
        System.out.println(s.replaceFirst("c","-"));
    }
}

运行截图:

注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串。

4.4 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

方法 功能
String[] split(String regex) 将字符串全部拆分
String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组

public class Test9 {
    public static void main(String[] args) {
        String s = "2024-11-29";
        String[] strings = s.split("-");
        for (String str :strings){
            System.out.print(str+" ");
        }
        System.out.println();
        String[] strings1 = s.split("-",2);
        for (String str : strings1){
            System.out.print(str+" ");
        }
    }
}

注意事项:

1. 字符"|","*","+"都得加上转义字符,前面加上"\\".

2. 而如果是"\",那么就得写成"\\\\".

3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.

多次拆分:

public class Test9 {
    public static void main(String[] args) {
        String s = "name=zhangsan&age=18";
        String[] strings = s.split("&");
        for (String str : strings){
            String[] strings1 = str.split("=");
            System.out.println(strings1[0]+" "+strings1[1]);
        }
    }
}

输出截图:

4.5 字符串截取

从一个完整的字符串之中截取出部分内容。

方法 功能
String substring(int beginIndex) 从指定索引截取到结尾
String substring(int beginIndex, int endIndex) 截取部分内容

public class Test9 {
    public static void main(String[] args) {
        String s = "abcdefghijk";
        System.out.println(s.substring(5));
        System.out.println(s.substring(3, 6));//左闭右开
    }
}

运行截图:

注意事项:

1. 索引从0开始

2. 注意前闭后开区间的写法, substring(3, 6) 表示包含 3 号下标的字符, 不包含 6 号下标

4.6 其他操作

方法 功能
String trim() 去掉字符串中的左右空格,保留中间空格

trim 会去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等).

public class Test9 {
    public static void main(String[] args) {
        String s = "          hello \t\t";
        System.out.println(s);
        System.out.println(s.trim());
    }
}

运行截图:

五、StringBuilder和StringBuffer

因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下,因此:尽量避免对String的直接需要,如果要修改建议尽量使用StringBuffer或者StringBuilder。

public class Demo1 {
    public static void main(String[] args) {
        //获得毫秒级时间戳
        long start = System.currentTimeMillis();
        String s = "";
        for (int i = 0; i < 10000; i++) {
            s += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        start = System.currentTimeMillis();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            stringBuilder.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

运行截图:

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的。

方法 功能
StringBuff append(String str) 在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量
char charAt(int index) 获取index位置的字符
int length() 获取字符串的长度
int capacity() 获取底层保存字符串空间总的大小
void ensureCapacity(int mininmumCapacity) 扩容
void setCharAt(int index, char ch) 将index位置的字符设置为ch
int indexOf(String str) 返回str第一次出现的位置
int indexOf(String str, int fromIndex) 从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str) 返回最后一次出现str的位置
int lastIndexOf(String str, int fromIndex) 从fromIndex位置开始找str最后一次出现的位置
StringBuff insert(int offset, String str) 在offset位置插入:八种基类类型 & String类型 & Object类型数据
StringBuffer deleteCharAt(int index) 删除index位置字符
StringBuffer delete(int start, int end) 删除[start, end)区间内的字符
StringBuffer replace(int start, int end, String str) 将[start, end)位置的字符替换为str
String substring(int start) 从start开始一直到末尾的字符以String的方式返回
String substring(int start,int end) 将[start, end)范围内的字符以String的方式返回
StringBuffer reverse() 反转字符串
String toString() 将所有字符按照String的方式返回

String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可 以修改。频繁修改字符串的情况考虑使用StringBuilder。

注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:

String变为StringBuilder: 利用StringBuilder的构造方法或append()方法

StringBuilder变为String: 调用toString()方法。