Bootstrap

【重识Java】一文弄清Java字符串易混易错点

本文主要介绍一些关于Java字符串的易错易忘的知识点,并非系统完整介绍,如有在意,还请见谅。

一、字符串的概念

1.字符串到底是什么

💭:字符串的概念有什么好说的?😪

💬:这里不是的简单重复其一般性概念哦,而是专门指明Java中字符串的本质

在Java中,其实Java字符串就是Unicode字符序列。String 并不是Java内置的基本类型,而是由标准Java类库中提供的一个预定义类。

2.区别 码点 和 代码单元

🔔概念解释:

码点是指 一个编码表 中的 某个字符 对应的 代码值。
Unicode的码点分为17个代码级别,第一个级别是基本的多语言级别,码点从U+0000——U+FFFF,其余的16个级别从U+10000——U+10FFFF,其中包括一些辅助字符。

代码单元则是指在基本的多语言级别中,每个字符用16位表示代码单元。而辅助字符则采用一对连续的代码单元进行编码。

总之,一个码点既可以表示一个一般字符也可以表示一个辅助字符;而一个代码单元则只能表示一个一般字符,要两个代码单元才能表示一个辅助字符。

🚬 我的个人理解是:代码单元其实是一种抽象的单位1,为了方便遍历字符串中的一般字符和表示char类型字符的。

⭕️补充:如果想要了解更多关于编码的细节问题请看:
编码格式简介(ANSI、GBK、GB2312、UTF-8、GB18030和 UNICODE)

二、字符串的有趣方法

1.像切片一样获取子串

用过Python的应该知道Python有一个好用的处理字符串的方式叫做 切片,而在Java中同样有类似方法,并且规律相同,都是左闭右开。

🕑方法如下:

在这里插入图片描述

🕒代码实现如下:

在这里插入图片描述
🕓代码运行结果如下:

在这里插入图片描述

⭕️补充:从以上结果可以看出,substring(m,n) 方法------当m与n相等时,截取到的子串为空,并不会报错

2.拼接字符串

🔔解释:
在Java中,当一个字符串与一个非字符串的值进行拼接时,后者会被转换为字符串(其实任何一个Java对象都能转换为字符串,重写toString方法即可)而使用 + (加号)就可以拼接啦。

⭕️补充:在拼接多个字符串时,如果想要用一个界定符分隔它们,则可以使用String类的 静态join 方法

🕑方法如下:

在这里插入图片描述

🕒代码实现如下:

在这里插入图片描述

🕓代码运行结果如下:

在这里插入图片描述

3.处理码点和代码单元

经常使用的是获取代码单元,因为获取到代码单元经常与char字符进行比较或者其他处理,本文最后会给出一道算法题,其中就可以利用这个。

3.1获取长度

🕒代码实现如下

public class Article {
    public static void main(String[] args) {
        String str = "hi\uD835\uDD46"; //hi后面的其实是辅助字符:𝕆
        //获取字符串的代码单元长度
        int unit_len = str.length();
        //获取字符串的码点长度/码点数量
        int cpCount = str.codePointCount(0,unit_len);
        System.out.println("代码单元长度:"+unit_len);
        System.out.println("码点长度/数量:"+cpCount);
    }
}

🕓代码运行结果如下:

在这里插入图片描述
怎么样,是不是很有趣?😄

3.2获取索引为n处的值

🕒代码实现如下

public class Article {
    public static void main(String[] args) {
        String str = "hi\uD835\uDD46";
        //获取索引为1处的代码单元
        char first = str.charAt(1);
        //获取索引为1处的码点
        int cp = str.codePointAt(1);   
        //有意思的是码点长度为3,但却可以取到索引3处的值;这是为什么呢?
        System.out.println("代码单元:"+first);
        System.out.println("码点:"+cp);
    }
}

🕓代码运行结果如下:

在这里插入图片描述

4.将字符串转为字符数组

🕑方法如下:

在这里插入图片描述

🕒代码实现如下

public class Article {
    public static void main(String[] args) {
        String str = "hi,windx";
        char[] c = str.toCharArray();
        for (int i = 0; i < c.length; i++) {
            System.out.print(c[i]+" ");
        }
    }
}

🕓代码运行结果如下:

在这里插入图片描述

5.其它方法(判别前后缀、去除空白符)

5.1 判别前后缀

有时我们通常会对一个字符串的前缀或后缀进行判断,看是否满足筛选条件,此时这个方法就能够派上用处了(如果用substring()的话有时会有意想不到的Bug)。

🕑方法如下:

①前缀:在这里插入图片描述
②后缀:
在这里插入图片描述
分别判断是否以某字符串开头、以某字符串结尾,均返回boolean类型值。

5.2 去除空白符

该方法可以删除原始字符串头部和尾部小于等于U+0020的字符或空格,同样用于对字符串进行处理。

🕑方法如下:
在这里插入图片描述

三、判断字符串是否相等

👉 首先要注意的是字符串是不可变的,当简单复制一个字符串时,其实是共享了同一处空间,只是复制了引用而已。

因此,

  • 使用 == 运算符判断两字符串是否相等,比较的只是两字符串的地址。
  • 如果要比较内容,需要使用equals()方法!而不区分大小写比较,则使用equalsIgnoreCase()方法。

⭕️补充:不论是使用 + 连接空字符串还是substring()获取子串或者进行大小写转换,都会改变字符串的地址

🕒代码测试如下

public static void main(String[] args) {
        String a = "aaa";
        String b = a;
        System.out.println("初始a的地址:");
        System.out.println("a:"+String.class.getName() + "@" + Integer.toHexString(System.identityHashCode(a)));
        a+="";
        if(b==a){
            System.out.println("b==a");
        }
        if(b.equals(a)){
            System.out.println("b.equals(a)");
        }
        System.out.println("与空串拼接后a的地址:");
        System.out.println("a:"+String.class.getName() + "@" + Integer.toHexString(System.identityHashCode(a)));
        System.out.println("b的地址:");
        System.out.println("b:"+String.class.getName() + "@" + Integer.toHexString(System.identityHashCode(b)));
    }

🕓代码运行结果如下:

在这里插入图片描述
可以看到由初始的a字符串复制的b字符串的地址与其初始地址是相等的,而a在拼接空串后,其地址发生了变化,但内容值不变。

⭕️补充:空串和null是两码事,字符串可以为空串 “”,也可以赋值为null,因为它本质是一个类对象。不可以对null调用字符串方法,因此常常需要判断是否为null。

时九月十九,秋意凉,不凉少年心。

;