深入理解Java字符类型与字符串

深入理解Java字符类型与字符串

1.Unicode编码

在讲解字符类型和字符串之前,要先要了解Unicode编码机制。在此之前要知道码点的概念,码点是指与一个编码表中的某个字符对应的代码值。在Unicode中,码点采用十六进制书写,并加上U+,例如U+0041是字符A的码点。Unicode的码点可以分为17个代码平面。其中,第一个代码平面称为基本多语言平面,包括从U+0000到U+FFFF的“经典”Unicode代码;其余16个代码平面的码点为从U+10000到U+10FFFF,包括辅助字符。
UTF-16编码采用不同长度的编码表示所有Unicode码点。在基本多语言平面,也就是Unicode编码中的第一个代码平面中,每个字符用16位表示,通常称为代码单元。而在其余的代码平面,即辅助字符的编码方式是用两个代码单元表示一个码点:首先,在基本多语言平面中,并没有用尽其中所有的值,还有2048个值是没有用到的,通常称为替代区域。在替代区域的U+D800到U+DBFF用于第一个代码单元,从U+DC00到U+FFFF用于第二个代码单元。所以可以根据代码单元来判断这个代码单元表示的是一个字符的编码,还是一个辅助字符的第一部分或第二部分。

基本数据类型:char

在Java中,char类型描述了UTF-16编码中的一个代码单元。这也许就是Java中char类型占两个字节的原因。所以char类型是不能定义一个辅助字符的。例如:’\u0041’表示A,𝕆是一个辅助字符,不能用char表示。

字符串String

Java字符串就是Unicode字符序列,例如“Java\u2122”就是由5个Unicode字符:J、a、v、a、™组成。需要注意的是字符串不是Java内置的数据类型,而是一个预定义类,这也许就是它的首字母需要大写,叫String的原因吧。其中,每个用双引号括起来字符串的都是String类的实例,即对象。所以可以根据对象来访问String类中的方法。下面将与方法结合说明字符串。

substring方法(截取字符串)

substring方法是截取出整个字符串中的一个子串。使用方法如下:

String greeting = "hello";
String s;
s = greeting.substring(0, 3);
System.out.println(s);

输出

hel

和数组一样,字符串中的字符也是从0开始计数的。所以substring方法的第一个参数是开始截取字符的位数,第二个参数是截取终止字符的后一个位数。
像下图这样,第一个参数是开始h的位数0,第二个参数是所截取的最后一个字符的下一个位数3。
在这里插入图片描述
不仅可以通过字符串变量访问字符String类中的方法,也可以通过字符串本身访问String类中的方法。像这样:

System.out.println("HelloWorld".substring(5, 10));

输出:

World

也可以通过Java的jshell来验证:(Java9新增的特性,在windows命令窗口输入jshell即可打开)

  • 字符串变量名可以访问到的方法:
    在这里插入图片描述
  • 字符串本身可以访问到的方法
    在这里插入图片描述
    可以看到它们访问到的方法是相同的。此外,jshell可以很好地查看类中的方法,这点对我这个新手来说太好了。

join方法()(连接方法)

Java中可以使用+号拼接字符串。若字符串与非字符串相接,非字符串会转换成字符串。
例如字符串与变量相接,变量会转换为字符串。举个例子:

int year = 2021;
int month = 8;
int day = 29;
System.out.println("今天是" + year + "年" + month + "月" + day + "日");

输出:

今天是2021829

以上只是顺带说一下,下面进入正题。直接看代码:

String greeting;
greeting = String.join("/", "S", "M", "L", "XL");
System.out.println(greeting);

输出:

S/M/L/XL

由上述代码结果就可以分析出join方法的作用了。

repeat方法(重复方法)

注意:此方法在Java11添加。比较容易,看代码吧。

System.out.println("Java".repeat(3));

输出:

JavaJavaJava

可以看到,字符串Java重复了三次输出。

equals方法(检测两个字符串是否相等)

在Java中,是不可以用==来检测字符串是否相等的,它只能检测两个字符串在内存中是否存放在同一个地方。当然,存放在同一个地方的字符串一定相等,但如果两个字符串相等但不存放在同一个地方,返回的也是假。
检测字符串相等可以用equals方法,当字符串相等时,返回true。代码见下。

      String greeting = "hello";
      String s = "hello";
      if (greeting.equals(s))
          System.out.println("yes");
      else
          System.out.println("no");

输出:

yes

length方法

length方法可以看做求字符串长度的。不过length方法是求代码单元的数量作为长度。

String greeting = "hello\uD835\uDD46";
System.out.println("代码单元数量=" + greeting.length());

输出:

代码单元数量=7

如果要求码点的数量,我们可以用以下语句实现:

String greeting = "hello\uD835\uDD46";
System.out.println("码点数量=" + greeting.codePointCount(0, greeting.length()));

输出:

码点数量=6

所以我们可以知道codePointCount方法是求给定范围的码点数量。

charAt方法

调用s.charAt(n)的作用是返回位置为n的代码单元,n在0到s.length()-1的范围内。

String s = "hello";
char first = s.charAt(0);
System.out.println(first);
char last = s.charAt(4);
System.out.println(last);

输出:

h
o

offsetByCodePoints方法

这个方法是这样调用的:

String s = "hello";
int index = s.offsetByCodePoints(1, 2);
System.out.println(index);

输出:

3

为什么会输出3呢?这是因为这个方法的第一个参数是字符串中一个码点的索引,可以看到是1,而第二个参数是从第一个参数的那个码点位置起,向后推移的码点数,返回值就是推移后码点的索引,所以,1向后推移两格,就是3了。用图来看形象一点。

在这里插入图片描述

codepointAt方法

这个方法的作用是获取码点。可以和上文说的offsetByCodePoints配合使用。像下面这样:

String greeting = "hello";
int index = greeting.offsetByCodePoints(0, 2);
int codePoint = greeting.codePointAt(index);
System.out.printf("%x", codePoint);

输出:

6c

可以看到输出的十六进制的码点为6c,根据上文提到的offsetByCodePoints方法,可以推测得到的字符串索引为3,那么也就是l这个字母。下面我们来看看字母l的十六进制输出:

int l = (int) 'l';
System.out.printf("%x", l);

输出:

6c

可以看到,是相同的。也就是说codePointAt方法得到了字母l的码点。为什么要用到offsetByCodePoints方法呢?这是因为这个方法返回来的是个码点的索引,而不是代码单元的索引,所以由这个方法返回来的一定是个码点的索引。例如像下面这样是运行不成功的:

String greeting = "hello\uD835\uDD46";
int index = greeting.offsetByCodePoints(0, 6);
int codePoint = greeting.codePointAt(index);
System.out.printf("%x\n", codePoint);

前文说过\uD835\uDD46是辅助字符𝕆的码点,当返回\uDD46时,由于它不是一个完整的码点,所以导致运行出错。正是由于这样,加上这个方法可以有效检验传入codePointAt方法的参数是否是一个真正的码点索引。

结语

有关字符和字符串的知识就介绍到这里了,也许 讲的很乱,讲的很基础。哎,谁让自己是个菜鸡呢?希望有一天可以深入理解吧。不说了文采太烂了,溜了溜了!😁

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值