• Java总结String类


    1. String类专门用来表示字符串类型
    2. 字符串构造的主要三种方法【学习一个类,先学习他的构造方法】
    public class TestDemo1 {
        public static void main(String[] args) {
            String s1 = "Hello";
            String s2 = new String("Hello");
    
            char[] array = {'H','e','l','l','o'};
            String s3 = new String(array);
    
            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s3);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    对于第三种方法,传入的是字符数组,转变成字符串,对应源码:

        public String(char value[]) {
            this.value = Arrays.copyOf(value, value.length);
        }
    
    • 1
    • 2
    • 3
    1. String是引用类型,内部并不存储字符本身,可以看到String类一个字符串对象里面包含2个成员变量,其中value是字符数组类型,字符串实际保存在char类型的数组中
      在这里插入图片描述

    那么上述s1和s2是如何存储的呢?
    在这里插入图片描述

    1. 字符串长度以及字符串是否为空
        public static void main(String[] args) {
            String s1 = "Hello";
            System.out.println(s1.length());
            System.out.println("Hello".length());
    
            String s2 = "";
            System.out.println(s2.isEmpty());
    
            String s3 = null;
            System.out.println(s3.isEmpty());
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行结果:
    在这里插入图片描述
    分析:①字符串长度的比较调用的是length()方法,而获取数组的长度是 int[] array = {1,2,3}; System.out.println(array.length);,一个有小括号,一个没有小括号,并且在Java中没有所谓的’\0’。
    在这里插入图片描述
    ②在Java中双引号“”引起来的也是String类型对象,也是字符串对象,因此可以直接使用"Hello".length(),可以看到点号.前面是个常量,因此不一定非得是变量调用字符串方法。
    ③s2字符串的长度为0,因此调用isEmpty()得到的返回值为true
    ④s3赋值为null,表示不指向任何对象,因此会抛出空指针异常
    注意:长度为0和指向null,这两种空是不一样的。

    1. String对象的比较
      ①==比较是否引用同一个对象
        public static void main(String[] args) {
            String s1 = "abc";
            String s2 = "abc";
            String s3 = s1;
            String s4 = new String("abc");
    
            System.out.println(s1 == s2);
            System.out.println(s1 == s3);
            System.out.println(s1 == s4);
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行结果:
    在这里插入图片描述
    分析:双引号引起来的值就存在字符串常量池当中,如果常量池中有abc就再重新存一份,直接返回字符串常量池中的对象即可。
    在这里插入图片描述
    对于基本类型变量,= =比较两个变量中存储的值是否相同;对于引用类型变量, = =比较两个引用变量引用的是否为同一个对象。
    ②boolean equals(Object anObject)方法比较对象内容是否相同:按字符比较
    String类重写了父类Object中equals方法,Object中的quals默认按照==比较,String重写equals方法后,则可以比较不同对象的内容是否相同,如果相同也可以返回true。

        public static void main(String[] args) {
            String s1 = new String("abc");
            String s2 = new String("abc");
            System.out.println(s1 == s2);
            System.out.println(s1.equals(s2));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    String类重写equals代码:

    public boolean equals(Object anObject) {
    //1、先检测this和anObject是否为同一个对象比较,如果是返回true
            if (this == anObject) {
                return true;
            }
    //2、检测anObject是否为String类型的对象,如果是继续比较,否则返回false
            if (anObject instanceof String) {
            //将anObject向下转型为String类型对象
                String anotherString = (String)anObject;
                int n = value.length;
                //3、this和anObject两个字符串的长度是否相同,如果是则继续比较,否则返回false
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    //4、从前往后逐个字符进行比较
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    运行结果:
    在这里插入图片描述
    如果要忽略大小写进行比较,使用equalsIgnoreCase()方法:

        public static void main(String[] args) {
            String s1 = new String("abc");
            String s2 = new String("Abc");
            System.out.println(s1.equalsIgnoreCase(s2));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果:
    在这里插入图片描述

    ③int compareTo(String s)方法比较字符串对象内容的大小:按照字典序进行比较
    注意:equals返回的是boolean类型,而compareTo返回的是int类型。
    比较方法:先按照字典次序大小比较,如果出现不相等的字符,则返回两个字符的ASCII大小差值;如果两个字符串的前K个字符都相等(K是两个字符串长度中的最小值),那么返回两个字符串长度的差值

        public static void main(String[] args) {
            String s1 = new String("abcd");
            String s2 = new String("abcd");
            String s3 = new String("abc");
    
            System.out.println(s1.compareTo(s2));
            System.out.println(s1.compareTo(s3));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果:
    在这里插入图片描述
    s1和s2字符串内容相同,所以返回0,s1和s3前3个字符相同,s1比s3长度多1,所以返回1.
    忽略大小写比较:s1.compareToIgnoreCase(s2)

        public static void main(String[] args) {
            String s1 = new String("abcd");
            String s2 = new String("Abcd");
    
            System.out.println(s1.compareTo(s2));
            System.out.println(s1.compareToIgnoreCase(s2));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:
    在这里插入图片描述

    1. 字符串查找
      ①char charAt(int index) 返回index位置上字符
        public static void main(String[] args) {
            String s = "abcdf";
            System.out.println(s.charAt(2));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述
    分析:s.charAt(2)返回下标为2的那个字符
    ②int indexOf(int ch) 返回ch第一次出现的位置,没有ch则返回-1

        public static void main(String[] args) {
            String s = "abcdf";
            System.out.println(s.indexOf('b'));
            System.out.println(s.indexOf('h'));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果:
    在这里插入图片描述
    分析:
    字符b在字符串中的下标是1,而字符串中没有h字符,所有第二条输出语句打印-1。
    ③int indexOf(int ch, int fromIndex) 从fromIndex位置开始找ch第一次出现的位置,没有则返回-1

        public static void main(String[] args) {
            String s = "abcdfasdfghsfdadbf";
            System.out.println(s.indexOf('b',6));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述
    分析:indexOf传入2个参数,则是从第6个位置开始找b字符
    ④int indexOf(String str) 【不仅可以找字符,还可以找字符串】返回str第一次出现的位置,没有返回-1

        public static void main(String[] args) {
            String s = "abcdfasdfghsfdadbf";
            System.out.println(s.indexOf("dfg"));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述
    分析:在字符串s中第一次出现子串dfg的下标位置是7
    ⑤int indexOf(String str, int fromIndex) 从fromIndex位置开始找str第一次出现的位置,没有返回-1

        public static void main(String[] args) {
            String s = "abcdfasdfghsfdadfgbf";
            System.out.println(s.indexOf("dfg",9));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述
    分析:从下标为9的位置开始找dfg

    上述是从前往后找也可以从后往前找
    ⑥int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置

        public static void main(String[] args) {
            String s = "abcdfasdfghsfdadfgbf";
            System.out.println(s.lastIndexOf('b'));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述
    ⑦int lastIndexOf(int ch, int fromIndex)从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1

        public static void main(String[] args) {
            String s = "abcdfasdfghsfdadfgbf";
            System.out.println(s.lastIndexOf('b',6));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述
    分析:从下标为6的位置开始,从后往前找
    ⑧int lastIndexOf(String str)从后往前找,返回str子串第一次出现的位置,没有返回-1

        public static void main(String[] args) {
            String s = "abcdfasdfghsfdadfgbf";
            System.out.println(s.lastIndexOf("dad"));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述
    ⑨int lastIndexOf(String str, int fromIndex)从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1

        public static void main(String[] args) {
            String s = "abcdfasdfghsfdadfgbf";
            System.out.println(s.lastIndexOf("dad",10));
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述

    1. 字符串与数值转化
      ①数值/对象转换成字符串 ——用String类的valueOf方法
    class Student{
    
    }
    public class TestDemo2 {
        public static void main(String[] args) {
            int a = 10;
            double b = 12.3;
            String s1 = String.valueOf(a);
            String s2 = String.valueOf(b);
            String s3 = String.valueOf(new Student());
    
            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s3);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行结果:
    在这里插入图片描述
    ②字符串转为基本数据类型数值——利用基本数据类型对应的包装类中的方法

        public static void main(String[] args) {
            String s1 = "123";
            String s2 = "12.34";
            int a = Integer.parseInt(s1);
            double b = Double.parseDouble(s2);
            System.out.println(s1);
            System.out.println(s2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果:
    在这里插入图片描述
    分析:parseInt和parseDouble两个方法都由static修饰,所以可以直接通过包装类名调用,而不用实例化对象。
    在这里插入图片描述
    在这里插入图片描述

    1. 字符串大小写转换
        public static void main(String[] args) {
            String s1 = "ABDFGSSDFsdfdgh";
            String s2 = s1.toLowerCase();
            String s3 = s1.toUpperCase();
            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s3);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果:
    在这里插入图片描述
    分析:s1.toLowerCase()将字符串中的大写字母全部转换成小写字母,s1.toUpperCase()将字符串中的小写字母全部转换成大写字母,并且可以发现s1中字符串的内容是不变的(String类的不可变性)。

    1. 数组和字符串之间的转换
      ①将数组转换成字符串,构造字符串对象,new String的时候传入字符数组进行构造
        public static void main(String[] args) {
            char[] chars = {'a','b','c'};
            String s = new String(chars);
            System.out.println(s);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ②将字符串转换成数组,用到了String类中的toCharArray()方法

        public static void main(String[] args) {
            String s = "hello";
            char[] chars = s.toCharArray();
            for (char i:chars) {
                System.out.println(i);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:
    在这里插入图片描述

    1. 字符串的格式化,用到String类中的format方法
        public static void main(String[] args) {
            String s = String.format("%d-%d-%d",2022,11,21);
            System.out.println(s);
        }
    
    • 1
    • 2
    • 3
    • 4

    运行结果:
    在这里插入图片描述

    1. 字符串替换
      使用一个指定的新的字符串替换掉已有的字符串数据
      replace的四种方法:
      在这里插入图片描述
        public static void main(String[] args) {
            String s = "abcdabd";
            String s1 = s.replace('a','x');
            String s2 = s.replace("abc","ooo");
            String s3 = s.replaceFirst("ab","00");
            String s4 = s.replaceAll("ab","00");
            System.out.println(s1);
            System.out.println(s2);
            System.out.println(s3);
            System.out.println(s4);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行结果:
    在这里插入图片描述
    注意:由于字符串是不可变对象,所以替换不修改当前字符串,而是产生一个新的字符串。

    1. 字符串拆分
      将一个完整的字符串按照指定的分隔符划分成为若干个字符串
      String[] split(String regex)将字符串全部拆分
      String[] split(String regex, int limit)将字符串以指定的格式,拆分为limit组
      注意:返回值类型是String[],字符串数组类型。
      例如:以空格分割字符串,得到字符串数组
        public static void main(String[] args) {
            String str = "Hello World Shuai Wang";
            String[] strings = str.split(" ");
            for (String x: strings) {
                System.out.println(x);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:
    在这里插入图片描述
    在上述例子中,可以给split方法再添加一个参数,指定拆分成几组。

        public static void main(String[] args) {
            String str = "Hello World Shuai Wang";
            String[] strings = str.split(" ",2);
            for (String x: strings) {
                System.out.println(x);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:分成2组
    在这里插入图片描述
    例子:拆分IP地址,有些特殊字符作为分隔符可能无法正确拆分,需要加上转义。

        public static void main(String[] args) {
            String str = "192.168.0.1";
            String[] strings = str.split("\\.");
            for (String x:strings) {
                System.out.println(x);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:
    在这里插入图片描述
    分析:此处以点号.进行分割,需要加2个反斜杠,第一个反斜杠表示:点号.需要转义;第二个反斜杠表示:刚刚那个反斜杠需要转义。(如果没有加反斜杠,则没有打印结果)
    注意:
    ①字符“|”,“*”,“+”都需要加上转义字符,前面加上“\”【2个斜杠才能表示1个斜杠】
    ②如果是“\”,而需要写成“\\”【4个斜杠才能表示2个斜杠】
    如果一个字符串中有多个分隔符,可以用“|”作为连字符
    例子:多次拆分
    ①用到连字符|

        public static void main(String[] args) {
            String str = "name=zhangsan&age=21";
            String[] strings = str.split("=|&");
            for (String x:strings) {
                System.out.println(x);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ②用到for循环多次拆分

        public static void main(String[] args) {
            String str = "name=zhangsan&age=21";
            String[] strings = str.split("=");
            // name zhangsan&age 21
            for (int i = 0; i < strings.length; i++) {
                //对数组的每个元素再进行分割
                String[] ret = strings[i].split("&");
                //对数组每个元素分割之后进行打印
                for (String x: ret) {
                    System.out.println(x);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    运行结果:
    在这里插入图片描述

    1. 字符串截取
      从一个完整的字符串里面截取出部分内容
        public static void main(String[] args) {
            String str = "abcdsasffsa";
            String s1 = str.substring(2);
            String s2 = str.substring(2,7);
            System.out.println(s1);
            System.out.println(s2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:
    在这里插入图片描述
    分析:
    String substring(int beginIndex)表示从指定索引截取到结尾
    String substring(int beginIndex, int endIndex)表示截取某个区间,截取部分内容,区间为左闭右开

    1. 观察trim()方法的使用
      trim会去掉字符串开头和结尾的空白字符(空格、换行、制表符等),保留中间空格
        public static void main(String[] args) {
            String str = "   Hello    World      ";
            String s1 = str.trim();
            System.out.println(str);
            System.out.println(s1);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行结果:
    在这里插入图片描述

    1. 字符串的不可变性
      String是一种不可变对象,字符串中的内容是不可改变的,字符串不可被修改。
      其原因是:
      在这里插入图片描述
      并不是因为String类被final修饰所以字符串不可被修改。被fianl修饰只能说明String类不可以被继承。
      真正的原因是:value被final修饰,而且权限是private。value被final修饰,表明value自身的值是不能改变的,即它引用的数组对象的地址是不能改变的,但是它引用的数组对象里面的内容还是可以修改的。又因为被private修饰,所以无法在类外进行修改其引用的数组对象里面的内容。因此String不可变。
        public static void main(String[] args) {
            final int[] array = {1,2,3,4};
            array = new int[6];
            array[0] = 6;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代码中,array数组被final修饰,代表array引用所指向的对象地址不能改变,所以 array = new int[6];会报错,而其对象的内容可以修改,例如 array[0] = 6;可以编译运行成功。
    即:final修饰类表示该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。

    1. 字符串修改:拼接过程中会产生新的临时对象。
        public static void main(String[] args) {
            String str = "Hello";
            str += "World";
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    观察其反汇编程序
    在这里插入图片描述
    可以发现其实际代码为:

        public static void main(String[] args) {
            String str = "Hello";
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(str);
            stringBuilder.append("World");
            str = stringBuilder.toString();
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    分析:这种字符串拼接的方式不推荐使用,因为其效率非常低,中间创建了很多临时对象。因此:尽量避免对String的直接修改,如果需要修改尽量使用StringBuffer和StringBuilder。

    1. StringBuffer和StringBuilder
      由于String的不可更改特性,为了方便字符串的修改,Java中提供了StringBuffer和StringBuilder类。
      ①常用方法——append()
        public static void main(String[] args) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("abc").append("hello");
            stringBuilder.append("World");
            stringBuilder.append(123);
            System.out.println(stringBuilder);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    append方法的源码:

        public StringBuilder append(String str) {
            super.append(str);
            return this;
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可以看到return的是this,返回的就是当前对象,此时不会产生临时对象。
    ②常用方法——toString() 将所有的字符转换成String类型并返回

        public static void main(String[] args) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("abc").append("hello");
            stringBuilder.append("World");
            stringBuilder.append(123);
            String str = stringBuilder.toString();
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    toString的源码:

        public String toString() {
            // Create a copy, don't share the array
            return new String(value, 0, count);
        }
    
    • 1
    • 2
    • 3
    • 4

    分析:可以发现toString创建了一个新的String对象。

    1. String和StringBulider/StringBuffer类的互相转换
      ①String类变成StringBulider:通过append方法或者StringBulider的构造方法
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("abc").append("hello");
            stringBuilder.append("World");
    
    • 1
    • 2
    • 3

    ②StringBulider变成String:通过调用StringBulider的toString()方法

           StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("abc");
            String str = stringBuilder.toString();
            System.out.println(str);
    
    • 1
    • 2
    • 3
    • 4
    1. String、StringBulider、StringBuffer的区别
      ①String的内容不可修改,StringBulider和StringBuffer的内容可以修改
      ②StringBulider和StringBuffer大部分的功能是相似的
      ③StringBuffer采用同步处理,属于线程安全操作;StringBuilder未采用同步处理,属于线程不安全操作
      在这里插入图片描述
      分析:synchronized(锁)用在多线程情况下,所以StringBuffer更安全。【但是频繁的加锁和释放锁都是需要耗费系统资源的】

    2. 以下总共创建了多少个String对象【不考虑常量池之前是否存在】

        String str = new String("ab");
        String str = new String("a") + new String("b");
    
    • 1
    • 2

    分析:第一条语句产生2个String对象,第二条语句产生5个String对象+1个StringBulider对象
    ①“ab”双引号引起来的是一个字符串对象,new String new了一个字符串对象,所以一个2个
    ②“a”和"b"2个双引号引起来,则产生了2个字符串对象,2个new则new了2个字符串对象,+字符串拼接会产生一个StringBulider对象,StringBulider对象最后调用toString方法会new一个String对象,所以会产生5个String对象,1个StringBulider对象,总共6个对象。

  • 相关阅读:
    对自己LRU算法代码的优化
    springboot+vue+Elementui共享单车管理系统
    【python编程从入门到实践】P2 变量的规范
    java_springboot水果购物商城销售管理系统
    C现代方法(第1&2章)笔记——概述、基本概念
    MFC Windows 程序设计[235]之写矩形和圆形DXF文件(附源码)
    对象序列化运用
    es的nested查询
    领夹直播麦克风常规的使用方法及方案说明
    javascript中BOM对象
  • 原文地址:https://blog.csdn.net/weixin_44070116/article/details/127960079