Java总结String类
创始人
2024-02-05 04:21:35
  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是否为同一个对象比较,如果是返回trueif (this == anObject) {return true;}
//2、检测anObject是否为String类型的对象,如果是继续比较,否则返回falseif (anObject instanceof String) {//将anObject向下转型为String类型对象String anotherString = (String)anObject;int n = value.length;//3、this和anObject两个字符串的长度是否相同,如果是则继续比较,否则返回falseif (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 21for (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 arrayreturn 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个对象。

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...