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);

    }
}

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

    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
  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());

    }

运行结果:
在这里插入图片描述
分析:①字符串长度的比较调用的是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);

    }

运行结果:
在这里插入图片描述
分析:双引号引起来的值就存在字符串常量池当中,如果常量池中有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));
    }

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;
    }

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

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

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

③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));
    }

运行结果:
在这里插入图片描述
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. 字符串查找
    ①char charAt(int index) 返回index位置上字符
    public static void main(String[] args) {
        String s = "abcdf";
        System.out.println(s.charAt(2));
    }

运行结果:
在这里插入图片描述
分析: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'));
    }

运行结果:
在这里插入图片描述
分析:
字符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));
    }

运行结果:
在这里插入图片描述
分析: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"));
    }

运行结果:
在这里插入图片描述
分析:在字符串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));
    }

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

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

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

运行结果:
在这里插入图片描述
⑦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));
    }

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

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

运行结果:
在这里插入图片描述
⑨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. 字符串与数值转化
    ①数值/对象转换成字符串 ——用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);

    }
}

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

    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);
    }

运行结果:
在这里插入图片描述
分析: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);
    }
}

运行结果:
在这里插入图片描述
分析: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);
    }

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

    public static void main(String[] args) {
        String s = "hello";
        char[] chars = s.toCharArray();
        for (char i:chars) {
            System.out.println(i);
        }
    }

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

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

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

  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. 字符串拆分
    将一个完整的字符串按照指定的分隔符划分成为若干个字符串
    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);
        }
    }

运行结果:
在这里插入图片描述
在上述例子中,可以给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);
        }
    }

运行结果:分成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);
        }
    }

运行结果:
在这里插入图片描述
分析:此处以点号.进行分割,需要加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);
        }
    }

②用到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. 字符串截取
    从一个完整的字符串里面截取出部分内容
    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);
    }

运行结果:
在这里插入图片描述
分析:
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. 字符串的不可变性
    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;
    }

代码中,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);
    }

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

    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);
    }

分析:这种字符串拼接的方式不推荐使用,因为其效率非常低,中间创建了很多临时对象。因此:尽量避免对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);
    }

append方法的源码:

    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

可以看到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);
    }

toString的源码:

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

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

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

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

       StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("abc");
        String str = stringBuilder.toString();
        System.out.println(str);
  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");

分析:第一条语句产生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个对象。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeKnightShuai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值