我的主页
【Java SE 专栏】
上一篇文章:带你走近Java的抽象类与接口

文章目录

  • 1. String类的重要性
    • 2. String类常用方法
    • 2.1 字符串构造
    • 2.2 String对象的比较
    • 2.3 字符串查找
    • 2.4 转化
    • 2.5 字符串替换
    • 2.6 字符串拆分
    • 2.7 字符串截取
    • 2.8 字符串的不可变性
    • 2.11 字符串修改
      • 3.StringBuilder和StringBuffer
    • 3.1 StringBuilder的介绍

1. String类的重要性

在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字符串应用又非常广泛,因此Java语言专门提供了String类。

2. String类常用方法

2.1 字符串构造

String类提供的构造方式非常多,常用的就以下三种:
1.使用常量串构造,也称字符串赋值

String str = "hello";

2.直接newString对象

 String str1 = new String("hello,world");

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

char[] array = {'1','2','3','4'};String str2 = new String(array);

将数组名作为形参传到String的构造函数之后,调用了数组的复制方法copyof,然后返回的类型是String类型。

【注意】

  1. String是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:

    字符串中的内容实际存储在value[]数组当中。

字符串是引用类型,并不直接存储字符串的内容,而是存储的是引用变量的地址。
以下代码和画图演示可以证明:

 public static void main(String[] args) {My_String.fun();String str1 = new String("1234");String str2 = new String("12");String str3 = str1;System.out.println(str1.length());System.out.println(str3.isEmpty());}

str1的引用变量的地址赋值给了str3,此时的str3引用变量存储的是str1的地址,这样也可以通过str3引用变量来指向str1中的字符串的内容。
上述的打印结果分别是4,和false则可以证明这个结论。

结果显示,结论正确。
就接下来看看画图演示:

2. 在Java中“”引起来的也是String类型对象。

System.out.println(str1.length());System.out.println(str3.isEmpty());System.out.println("hello".length());

2.2 String对象的比较

字符串的比较是常见操作之一,比如:字符串排序。Java中总共提供了4中方式:

  1. “== “比较是否引用同一个对象

对于简单类型”“是比较数值的大小,而对于引用类型“”是比较引用变量的地址。

public static void main(String[] args) {//简单类型int a = 10;int b = 10;//引用类型String str1 = new String("abcdefg");String str2 = new String("abcdefg");//比较简单类型System.out.println(a == b);//truefalse//比较引用类型System.out.println(str1 == str2);}}

结果显示:在基本类型中比较的是数值,而在引用类型当中比较的是地址。
2. boolean equals(Object anObject) 方法:按照字典序比较:
比较返回类型为boolean类型,相同则返回true不相同则返回false
字典序:字符大小的顺序,字符大小:字符返回的ASCII值。
String类重写了父类Object中equals方法,Object中equals默认按照==比较:

 public boolean equals(Object obj) {return (this == obj);}

因为object中equals默认按照==比较,所以我们要在String类中重写equals方法:

//在String中重写的equals方法:public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;}

接下来我们来通过str1.equals(str2)比较引用类型的内容:

public static void main(String[] args) {String str1 = new String("abcdefg");String str2 = new String("abcdefg");String str3 = new String("ABCDEFG");System.out.println(str1.equals(str2));System.out.println(str1.equals(str3));}


通过重写equals方法,我们就可以用字典序来比较字符串的大小了。
在比较字符串的大小的时候:
第一步:我们通过字典序来比较。
第二步:当字典序相同的时候,我们可以通过字符串的长度来比较。
3. int compareTo(String s) 方法: 按照字典序进行比较:
这个和equals不同的是,返回类型不是boolean类型而是int类型,比较方式:

  1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
  2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
 public static void main(String[] args) {String str1 = new String("abcdefg");String str2 = new String("abcdefg");String str3 = new String("ABCDEFG");System.out.println(str1.compareTo(str2));System.out.println(str1.compareTo(str3));}


4. int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较:

public static void main(String[] args) {String str1 = new String("abcdefg");String str2 = new String("abcdefg");String str3 = new String("ABCDEFG");String str4 = new String("zhangsan");System.out.println(str1.compareToIgnoreCase(str2));System.out.println(str1.compareToIgnoreCase(str3));System.out.println(str1.compareToIgnoreCase(str4));}

2.3 字符串查找

字符串查找也是字符串中非常常见的操作,String类提供的常用查找的方法:

  1. public char charAt(int index)从字符串中拿到一个字符。

在String类中的方法是这么实现的。

自己来实现一下这个方法:

public static void main(String[] args) {String str1 = new String("abcdef");char ch = str1.charAt(0);//'a'char ch1 = str1.charAt(1);//'b'char ch2 = str1.charAt(-1);//抛异常char ch3 = str1.charAt(6);//抛异常System.out.println(ch);System.out.println(ch1);System.out.println(ch2);System.out.println(ch3);}
  1. int indexOf(int ch) 返回字符的下标,找不到就返回-1,从头开始一个一个找。
    我们来实现一下这个方法:
public static void main(String[] args) {String str1 = new String("abcdef");System.out.println(str1.indexOf('a'));System.out.println(str1.indexOf('b'));System.out.println(str1.indexOf('z'));}


3. int indexOf(int ch, intfromIndex) 从指定位置开始找这个字符,找到返回下标,找不到就返回-1。
我们来实现这个方法:

 public static void main(String[] args) {String str = new String("hello");System.out.println(str.indexOf('l', 3));}


4. int indexOf(String str) 从头开始在字符串A找字符串B,找到了返回字符串A中字符串B的第一个下标,比如:字符串A”hello”,字符串B”llo”则返回”llo”在字符串A的下标,找不到就返回-1.
我们来实现这个方法:|

 public static void main(String[] args) {String str = new String("hello");System.out.println(str.indexOf("llo"));System.out.println(str.indexOf("all"));}


5 . int indexOf(String str, intfromIndex) 在指定位置从字符串A中找字符串B,找到还是一样返回字符串A中字符串B的第一个下标。找不到返回-1.
我们来实现这个方法:

public static void main(String[] args) {String str = new String("hello");System.out.println(str.indexOf("llo", 2));System.out.println(str.indexOf("llo", 4));}


6. int lastIndexOf(int ch) 从字符串最后的位置找目标字符,找到就返回其下标,找不到就返回-1.
我们来实现这个方法:

 public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf('o'));System.out.println(str.lastIndexOf('a'));}


**【注意】**这个找到的下标还是从前往后数的下标,而不是从后往前数的。
7. int lastIndexOf(int ch, intfromIndex) 这个是从指定位置,往后找这个字符,找到返回其下标,找不到就返回-1.
我们来实现这个方法:

 public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf('l', 4));System.out.println(str.lastIndexOf('l', 1));


8. int lastIndexOf(String str) 从后往前在字符串A中找字符串B,找到了返回字符串A中字符串B的第一个下标,找不到就返回-1.
我们来实现这个方法:

 public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf("llo"));System.out.println(str.lastIndexOf("lle"));


9. int lastIndexOf(String str, intfromIndex) 从指定位置从后往前在字符串A中找字符串B,找到了返回字符串A中字符串B的第一个下标,找不到就返回-1.
我们来实现这个方法:

public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf("llo", 4));System.out.println(str.lastIndexOf("llo", 1));

2.4 转化

1. 数值和字符串转化

public static void main(String[] args) {//数字转字符串String str = String.valueOf(123);System.out.println(str);//字符串转数字Integer ii = Integer.valueOf("123");System.out.println(ii);}

字符串转化其他类型,构成了一个重载方法:String.valueOf()

其他类型转化String类型:
Integer.valueOf()
Float.valueOF()

2. 大小写转换

public static void main(String[] args) {String str = new String("abc");String str1 = new String("ABC");//小写转化为大写System.out.println(str.toUpperCase());//大写转化小写System.out.println(str1.toLowerCase());}


3. 字符串转数组
字符串转化数组
toCharArray()

 public static void main(String[] args) {String str ="abc";char[] chars = str.toCharArray();System.out.println(Arrays.toString(chars));}


数组转化为字符串

 public static void main(String[] args) {char[] chars = {'1','2','3'};String str = new String(chars);System.out.println(str);}

4.格式化
String.format()

public static void main(String[] args) {String s = String.format("%d-%d-%d", 2019, 9,14);System.out.println(s);}

2.5 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:
1.String replaceAll(String regex, String replacement) 替换所有指定的内容
String regex:被替换的内容
String replacement:替换的内容

public static void main(String[] args) {String str = "helloworld";System.out.println(str.replaceAll("l", "+"));}

2.String replaceFirst(String regex, String replacement) 替换首个内容
String regex:在被替换的内容中出现第一次的内容
String replacement:替换的内容

 public static void main(String[] args) {String str = "helloworld"; System.out.println(str.replaceFirst("l", "+"));}


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

2.6 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
可用方法如下:
1.String[] split(String regex) 将字符串全部拆分,将字符串拆分,用字符串数组来接收。
String regex:以指定的格式拆分

public static void main(String[] args) {String str = "hello world java SE";String[] ret = str.split(" ");for (String s:ret) {System.out.println(s);}}

2.String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组
String regex:以指定的格式拆分
int limit:拆分几组

public static void main(String[] args) {String str = "hello world java SE";String[] ret = str.split(" "2);for (String s:ret) {System.out.println(s);}}

注意事项:

  1. 字符”|“,”*“,”+”都得加上转义字符,前面加上 “\” .
  2. 而如果是 “” ,那么就得写成 “\\” .
  3. 如果一个字符串中有多个分隔符,可以用”|”作为连字符.

2.7 字符串截取

从一个完整的字符串之中截取出部分内容。可用方法如下:
1.String substring(int beginIndex) 从指定位置截取到结尾
int beginIndex:指定位置

String str = "helloworld" ;System.out.println(str.substring(5));

2.String substring(int beginIndex, int endIndex) 截取部分内容
int beginIndex:截取的开始位置
int endIndex: 截取的结束位置

String str = "helloworld" ;System.out.println(str.substring(0, 5));

注意事项:

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

2.8 字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:
1. String类在设计时就是不可改变的,String类实现描述中已经说明了:


String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:

  1. String类被final修饰,表明该类不能被继承
  2. value被修饰被final修饰,只能引用当前初始化好的对象不能引用其他对象,但是其引用空间中的内容可以修改。
    2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象

最后总结一下:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。这种说法是错误的。
字符串不可变的原因有两点:
1.String类被final修饰,表明该类不能被继承
2.value被修饰被final修饰,只能引用当前初始化好的对象不能引用其他对象,但是其引用空间中的内容可以修改

2.11 字符串修改

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。
我们通过拼接符“+”确实可以对字符串进行修改,但是这样的效率太慢了。

public static void main(String[] args) {String s = "hello";s += " world";System.out.println(s); // 输出:hello world}

但是这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象。
关于这些临时变量怎么可以看到,我们可以通过反汇编的方式可以看到:


根据上面的图片我们可以看到有两个新的类:StringBuilder和StringBuffer
在这两个类中字符串是可以改变的。
接下来我们来看看这两个类把!

3.StringBuilder和StringBuffer

3.1 StringBuilder的介绍

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


从上述方法可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。
这些方法我就不一一解释了,和上述String类方法差不多。
结尾:
希望大家可以给我点点关注,点点赞,你们的支持就是我的最大鼓励。