面向对象篇【字符串】String类 StringBuilder类 正则表达式

@


字符串

字符串类是一个比较特殊的类,它用于保存字符串。我们知道,基本类型char可以保存一个2字节的Unicode字符,而字符串则是一系列字符的序列(在C中就是一个字符数组)Java中没有字符串这种基本类型,因此只能使用类来进行定义。注意,字符串中的字符一旦确定,无法进行修改,只能重新创建。

String类

String本身也是一个类,只不过它比较特殊,每个用双引号括起来的字符串,都是String类型的一个实例对象:

public static void main(String[] args) {
    String str = "Hello World!";
}

我们也可以象征性地使用一下new关键字:

public static void main(String[] args) {
    String str = new String("Hello World!");  //这种方式就是创建一个新的对象
}

注意,如果是直接使用双引号创建的字符串,如果内容相同,为了优化效率,那么始终都是同一个对象:

public static void main(String[] args) {
    String str1 = "Hello World";
    String str2 = "Hello World";
    System.out.println(str1 == str2);
}

但是如果我们使用构造方法主动创建两个新的对象,那么就是不同的对象了:

public static void main(String[] args) {
    String str1 = new String("Hello World");
    String str2 = new String("Hello World");
    System.out.println(str1 == str2);
}

至于为什么会出现这种情况,我们在JVM篇视频教程中会进行详细的介绍,这里各位小伙伴只需要记住就行了。因此,如果我们仅仅是想要判断两个字符串的内容是否相同,不要使用==,String类重载了equals方法用于判断和比较内容是否相同:

public static void main(String[] args) {
    String str1 = new String("Hello World");
    String str2 = new String("Hello World");
    System.out.println(str1.equals(str2));   //字符串的内容比较,一定要用equals
}

既然String也是一个类,那么肯定是具有一些方法的,我们可以来看看:

public static void main(String[] args) {
    String str = "Hello World";
    System.out.println(str.length());   //length方法可以求字符串长度,这个长度是字符的数量
}

因为双引号括起来的字符串本身就是一个实例对象,所以说我们也可以直接用:

public static void main(String[] args) {
    System.out.println("Hello World".length());   //虽然看起来挺奇怪的,但是确实支持这种写法
}

字符串类中提供了很多方便我们操作的方法,比如字符串的裁剪、分割操作:

public static void main(String[] args) {
    String str = "Hello World";
    String sub = str.substring(0, 3);   //分割字符串,并返回一个新的子串对象
    System.out.println(sub);
}
public static void main(String[] args) {
    String str = "Hello World";
    String[] strings = str.split(" ");   //使用split方法进行字符串分割,比如这里就是通过空格分隔,得到一个字符串数组
    for (String string : strings) {
        System.out.println(string);
    }
}

字符数组和字符串之间是可以快速进行相互转换的:

public static void main(String[] args) {
    String str = "Hello World";
    char[] chars = str.toCharArray();
    System.out.println(chars);
}
public static void main(String[] args) {
    char[] chars = new char[]{'奥', '利', '给'};
    String str = new String(chars);
    System.out.println(str);
}

当然,String类还有很多其他的一些方法,这里就不一一介绍了。

StringBuilder类

我们在之前的学习中已经了解,字符串支持使用++=进行拼接操作。

但是拼接字符串实际上底层需要进行很多操作,如果程序中大量进行字符串的拼接似乎不太好,编译器是很聪明的,String的拼接会在编译时进行各种优化:

public static void main(String[] args) {
    String str = "杰哥" + "你干嘛";    //我们在写代码时使用的是拼接的形式
    System.out.println(str);
}

编译之后就变成这样了:

public static void main(String[] args) {
    String str = "杰哥你干嘛";
    System.out.println(str);
}

对于变量来说,也有优化,比如下面这种情况:

public static void main(String[] args) {
    String str1 = "你看";
    String str2 = "这";
    String str3 = "汉堡";
    String str4 = "做滴";
    String str5 = "行不行";
    String result = str1 + str2 + str3 + str4 + str5;   //5个变量连续加
    System.out.println(result);
}

如果直接使用加的话,每次运算都会生成一个新的对象,这里进行4次加法运算,那么中间就需要产生4个字符串对象出来,是不是有点太浪费了?这种情况实际上会被优化为下面的写法:

public static void main(String[] args) {
    String str1 = "你看";
    String str2 = "这";
    String str3 = "汉堡";
    String str4 = "做滴";
    String str5 = "行不行";
    StringBuilder builder = new StringBuilder();
    builder.append(str1).append(str2).append(str3).append(str4).append(str5);
    System.out.println(builder.toString());
}

这里创建了一个StringBuilder的类型,这个类型是干嘛的呢?实际上它就是专门用于构造字符串的,我们可以使用它来对字符串进行拼接、裁剪等操作,它就像一个字符串编辑器,弥补了字符串不能修改的不足:

public static void main(String[] args) {
    StringBuilder builder = new StringBuilder();   //一开始创建时,内部什么都没有
    builder.append("AAA");   //我们可以使用append方法来讲字符串拼接到后面
    builder.append("BBB");
    System.out.println(builder.toString());   //当我们字符串编辑完成之后,就可以使用toString转换为字符串了
}

它还支持裁剪等操作:

public static void main(String[] args) {
    StringBuilder builder = new StringBuilder("AAABBB");   //在构造时也可以指定初始字符串
    builder.delete(2, 4);   //删除2到4这个范围内的字符
    System.out.println(builder.toString());
}

当然,StringBuilder类的编辑操作也非常多,这里就不一一列出了。

正则表达式

我们现在想要实现这样一个功能,对于给定的字符串进行判断,如果字符串符合我们的规则,那么就返回真,否则返回假,比如现在我们想要判断字符串是不是邮箱的格式:

public static void main(String[] args) {
    String str = "aaaa731341@163.com";
  	//假设邮箱格式为 数字/字母@数字/字母.com
}

那么现在请你设计一个Java程序用于判断,你该怎么做?是不是感觉很麻烦,但是我们使用正则表达式就可以很轻松解决这种字符串格式匹配问题。

正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。

我们先来看看下面的这个例子:

public static void main(String[] args) {
    String str = "oooo";
  	//matches方法用于对给定正则表达式进行匹配,匹配成功返回true,否则返回false
    System.out.println(str.matches("o+"));   //+表示对前面这个字符匹配一次或多次,这里字符串是oooo,正好可以匹配
}

用于规定给定组件必须要出现多少次才能满足匹配的,我们一般称为限定符,限定符表如下:

字符 描述
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。***** 等价于 {0,}
+ 匹配前面的子表达式一次或多次。例如,zo+ 能匹配 "zo" 以及 "zoo",但不能匹配 "z"+ 等价于 {1,}
? 匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 "do""does""doxy" 中的 "do"? 等价于 {0,1}
n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 "Bob" 中的 o,但是能匹配 "food" 中的两个 o
n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 "Bob" 中的 o,但能匹配 "foooood" 中的所有 oo{1,} 等价于 o+o{0,} 则等价于 o*
m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 "fooooood" 中的前三个 oo{0,1} 等价于 o?。请注意在逗号和两个数之间不能有空格。

如果我们想要表示一个范围内的字符,可以使用方括号:

public static void main(String[] args) {
    String str = "abcabccaa";
    System.out.println(str.matches("[abc]*"));   //表示abc这几个字符可以出现 0 - N 次
}

对于普通字符来说,我们可以下面的方式实现多种字符匹配:

字符 描述
[ABC] 匹配 [...] 中的所有字符,例如 [aeiou] 匹配字符串 "google runoob taobao" 中所有的 e o u a 字母。
[^ABC] 匹配除了 [...] 中字符的所有字符,例如 [^aeiou] 匹配字符串 "google runoob taobao" 中除了 e o u a 字母的所有字母。
[A-Z] [A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母。
. 匹配除换行符(\n、\r)之外的任何单个字符,相等于 [^\n\r]
[\s\S] 匹配所有。\s 是匹配所有空白符,包括换行,\S 非空白符,不包括换行。
\w 匹配字母、数字、下划线。等价于 [A-Za-z0-9_]

当然,这里仅仅是对正则表达式的简单使用,实际上正则表达式内容非常多,如果需要完整学习正则表达式,可以到:https://www.runoob.com/regexp/regexp-syntax.html

正则表达式并不是只有Java才支持,其他很多语言比如JavaScript、Python等等都是支持正则表达式的。

posted @ 2024-02-28 22:22  笠大  阅读(12)  评论(0编辑  收藏  举报