一、何为String?

    在学习C语言中,就已经涉及到了字符串的概念,但是在C语言中并没有字符串的类型,只能通过字符数组和字符指针的概念达到字符串的效果。
在这里插入图片描述
    但是中java里面专门提供了字符串类型:String,在C语言中没有字符串类型这样的说法。String属于引用型数据类型。

二、字符串的构造

    String类型的构造方法有很多,常用的有以下三种:

1、使用常量串构造

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

2、直接new String对象

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

3、使用字符数组进行构造

    public static void main(String[] args) {
        char[] ch = {'a' , 'b' , 'c' , 'd' , 'e' , 'f'};
        String s = new String(ch);
        System.out.println(s);
    }

    一般来说使用字符串常量构造是最常用的,但实际上字符串常量构造的本质就是new String,所以前两个方法本质上是一样的,只是使用字符串常量构造会比较迅速。

    public static void main(String[] args) {
        int[] array1 = {1,2,3,4};
        int[] array2 = new int[]{1,2,3,4};
    }

    和数组构造方法一样,两者没有区别,只是使用直接构造会比较迅速。

三、字符串的本质

    String是引用行数据类型,本身并不存储字符串,String类型的引用只用于存储对象的地址,以及调用相应的方法进行对对象的操作。
    在String的底层有一个Value数组,用于存储字符串,也就是说虽然Java定义了字符串类型,但本质是还是用数组进行存储字符串的,和C语言构造字符串有些类似,区别在于Java对该数组进行了封装,在字符串类型String的表面并看不出来从而达到了字符串类型的实现。
在这里插入图片描述
    在JDK1.8中,String的底层Value数组是char类型的,但是在JDk17中,Sting的底层Value数组是byte类型的。但两者并没有太大的区别,字符本质上就是数字,可以理解为String类当中的任何方法,都是对value数组进行操作的。
在这里插入图片描述
    引用型数据类型String的存储空间如图:

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

在这里插入图片描述
    所以说String本身并不存储字符串,而是存储String对象的地址。

三、String常用的方法

1、String对象的比较

1.1、String对象的比较:equals()

    对于基本数据类型来说,两者之间的比较可以直接用“==”进行比较
在这里插入图片描述
    但是对于引用行数据类型来说使用“ ==”进行比较并不合适,如图:s1和s2同样是“abc”,但比较结果确是不等于。
在这里插入图片描述
    对于基本数据类型来说:“= =”比较的是变量中的值
    对于引用型数据类型来说:“= = ”比较的是两个引用中存储的地址。
    这个时候我们就需要相应的方法进行比较String对象底层真正存储字符串的数组value,boolean equals(Object object)方法,按照字符大小的顺序进行比较
在这里插入图片描述
    String类中重写了Object中的equals方法,Object中的equals方法默认安装= =进行比较,但是在引用行数据类型并不适用,String重写equals方法后,按照字符大小的顺序进行一一比较。也就是真正的比较String类底层的value数组,而并非比较引用中的地址。

    需要注意的是:引用不能指向引用,一个引用只能指向一个对象。

        String s1 = new String("abc");
        String s2 = new String("abc");
        String s3 = s1;

    "s3 = s1"的意思并不是引用s3 指向 引用s1,而是引用s3指向了引用s1指向的对象。

1.2、忽略大小写的String对象的比较:equalsIgnoreCase(String s)

    在我们的生活中经常需要验证码进行登陆某某软件,我们可以发现验证码中输入过程中是忽略大小写的,只要是字母相同,大写小写都可以,String类当中当然也定义了忽略大小写比较的方法。
在这里插入图片描述

1.3、比较String对象的大小:compareTo(String s)

    与equals方法不同的是,equals返回的是boolean类型,compareTo方法返回的是int型的。具体比较方式:
    1、先按照字符大小的顺序进行比较,如果出现不相等字符,直接返回两者之间的差值
    2、如果两个字符串之间的长短不同,在比较过程中短的字符串先比较完了并且完全相同,此时返回字符串长度的差值。
在这里插入图片描述
    在使用compareTo()方法时,需要注意调用的顺序,顺序不同输出的差值不同

1.4、忽略大小写的String对象比较:compareToIgnoreCase(String s)

    和compareTo方法的使用方式一样,但是忽略大小写,同时有需要注意调用的顺序,并且该方法只能忽略字符,如果遇到中文会直接跳过。
在这里插入图片描述

2、字符串查找

在这里插入图片描述

    public static void main(String[] args) {
        String s = "aaabbbcccaaabbbccc";
        System.out.println(s.charAt(3));                        //'b
        System.out.println(s.indexOf('c'));                     //6
        System.out.println(s.indexOf('c',10));      //15
        System.out.println(s.indexOf("bbb"));                    //3
        System.out.println(s.indexOf("bbb",10));    //12
        System.out.println(s.lastIndexOf('c'));                 //17
        System.out.println(s.lastIndexOf('c',10));      //8
        System.out.println(s.lastIndexOf("bbb"));               //12
        System.out.println(s.lastIndexOf("bbb",10));    //3
    }

3、字符串转化

3.1、数值和字符串之间的转化valueOf()

    String.valueOf( X ),X可以是对象、int、boolean、double等数据类型,最终会返回对应的字符串。
在这里插入图片描述
     String.valueOf()方法在底层调用了toString方法,在类中重写的toString方法,重写toString方法可以按照自己的想法输出内容,并且仔细观察可以发现,在println()方法中也调用了String.valueOf()方法
在这里插入图片描述
     如果在类中没有重写toString方法,那么println()方法只能默认输出引用所存储的地址。

3.2、大小写的转化:toUpperCase(), toLowerCase()

     可以直接同过String的引用调用toUpperCase()方法和toLowerCase()方法,需要接收String类的返回值,String的方法都是返回一个new的String对象,不在原字符串上修改

    public static void main(String[] args) {
        String s = "AbcDef";
        String s1 = s.toLowerCase();//输出abcdef
        String s2 = s.toUpperCase();//输出ABCDEF
    }

3.3、字符串转数组:toCharArray()

     toCharArray()方法可以将字符串挨个转换成数组,需要用char类型的数组进行接收

    public static void main(String[] args) {
        String s = "AbcDef";
        char[] ch = s.toCharArray();
    }

     同时如果char类型的数组想转换为字符串,只需要将数组传给String的构造方法即可

    public static void main(String[] args) {
        String s = "AbcDef";
        char[] ch = s.toCharArray();
        
        String str = new String(ch);
    }

3.4、字符串格式化format()

    简而言之就是将内容通过自己规定的格式输出为字符串

    public static void main(String[] args) {
        String str = String.format("%d-%d-%d" , 2024,10,22);//str == 2024-10-22
    }

    需要注意的是format()方法的参数列表由第一个输入值决定,第一个输入值里面有多少个占位符,后面就要补充多少个数据,前后需要呼应。

4、字符串替换

4.1、替换所以指定的内容:replace()方法,replceAll()方法

    两个方法基本一致,但是不同的是replace()方法构有重载,可以替换字符或者字符串,但是replaceAll()方法只能替换字符串
在这里插入图片描述

        String str = "abcde";
        String s1 = str.replace("abc" , "aaa"); //aaade
        String s2 = str.replace('a' , 'b');         //bbcde
        String s3 = str.replaceAll("abc" , "aaa");//aaade
    }

4.2、替换首个内容:replaceFirst()

    替换调用者里面的首个内容,剩下的不变,并且将替换后的内容以new String的方式返回,需要用String类进行接收

    public static void main(String[] args) {
        String str = "abcabcabc";
        String s1 = str.replaceFirst("abc","aaa");//aaaabcabc
    }

    需要注意的是:由于字符串是不可变对象,替换不修改当前的字符串,而是产生新的字符串

5、字符串拆分

    split()方法可以将完整的字符串按照指定的分隔符拆分才若干个子字符串。
在这里插入图片描述
    split()方法也构成了重载,一个是不规定分割成多少个子字符串,一个是规定分割成limit个字符串

    public static void main(String[] args) {
        String str = "abc abc abc abc";
        String[] s1 = str.split(" ");           //abc  abc  abc  abc,分割成4个
        String[] s2 = str.split(" " , 2);   //abc  abc abc abc,分割成0个
    }

    但是比较需要注意的是,有一些特殊字符作为分隔符的时候可能无法正常分割,需要加上转义,比如拆分ip地址。

在这里插入图片描述

    split()方法没有正常运行,JDk无法识别“.”,因为“.”默认是一个操作符,用于调用类里面的方法或者变量,所以这个时候需要转义才可以使split()方法正常分割,需要在“.”前面加上“\”即可。
在这里插入图片描述
1、字符“|”,“*”,“+”都需要加上转义字符,前面加上“\”
2、如果是“\”字符,那么需要写成“\\”,因为“\”需要加上一个“\”转义才是真正的“\”的意思,那也就是说,在字符串里面需要用“\”的话就写成“\”,那么split()方法里面想要使用“\”作为分隔符,则方法里面想要写成“\\”
3、如果一个字符串中有多个分隔符,可以用“|”作为连字符
在这里插入图片描述

6、字符串截取

    从一个完整的字符串中截取部分内容,可以使用String.substring()方法。
在这里插入图片描述

    substring()方法也构成了重载,当参数列表只有一个时,表示截取该位置到字符串结尾的内容,如果参数列表有两个,表示截取范围内内容。并且是左闭右开,也就是第二个参数只能取到该位置的前一个内容,无法取到该位置上的内容

    public static void main(String[] args) {
        String str = "abcdef";
        String s1 = str.substring(3);//def
        String s = str.substring(2 , 5);//cde
    }

    需要注意的是,
1、索引是从0开始
2、注意前闭后开区间的写法,substring(0,5)表示保护0号下标的字符,但不包含5号下标的字符

7、去掉左右空格,保留中间空格

    trim()方法可以去掉字符串开头和结尾的空白字符,比如制表符,空格,换行等
在这里插入图片描述

四、String的注意事项

    String是一种不可变对象,字符串中的内容是不可变的,一旦初始化完成后就无法改变了,虽然可以使用“+=”进行字符串追加,但是并不是真正意义上的追加,“+=”实际上是new了几个新对象进行追加成为一个新的对象最后再返回变成String类型,本质意义上也不是在原字符串的基础上追加
    并且String类被final修饰,表示String类型不可以被继承
    String类的字符实际是保存在内部维护的value字符数组中,并且该数组也被final修饰,表示value本身的引用对象不可以修改,即不可以引用其他的字符数组,但是value引用的数组内容是可以修改的
    所有涉及到字符串内容修改的方法,都是创建一个新对象,改变的是新对象,而并非原对象,最终返回新对象

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐