type
status
date
slug
summary
tags
category
icon
password
Property
实际上字符串在
String
内部是通过一个char[]
数组表示的,因此按下面的写法也是可以的:因为
String
太常用了,所以Java提供了"..."
这种字符串字面量表示方法。Java字符串的一个重要特点就是字符串不可变。这种不可变性是通过内部的
private final char[]
字段,以及没有任何修改char[]
的方法实现的。字符串比较
当比较两个字符串是否相同时,要特别注意实际上是想比较字符串的内容是否相同,必须使用
equals()
方法而不能用==
:表面上看,两个字符串用
==
和equals()
比较都为true
,但实际上那只是Java编译器在编译期,会自动把所有相同的字符串当作一个对象放入常量池,自然s1
和s2
的引用就是相同的。所以这种==
比较返回true
纯属巧合,换一种写法就会失败:要忽略大小写比较,使用
equalsIgnoreCase()
方法搜索子串、提取子串
String
类还提供了多种方法来搜索子串、提取子串。常用的方法有:注意到
contains()
方法的参数是CharSequence
而不是String
,因为CharSequence
是String
的父类。搜索子串的更多的例子:
提取子串的例子:
去除首尾空白字符
使用
trim()
方法可以移除字符串首尾空白字符。空白字符包括空格,\t
,\r
,\n
:trim()
并没有改变字符串的内容,而是返回了一个新字符串。另一个
strip()
方法也可以移除字符串首尾空白字符。它和trim()
不同的是,类似中文的空格字符\u3000
也会被移除:String
还提供了isEmpty()
和isBlank()
来判断字符串是否为空和空白字符串:替换子串
要在字符串中替换子串,有两种方法。一种是根据字符或字符串替换:
另一种是通过正则表达式替换:
分割字符串
使用
split()
方法,并且传入的也是正则表达式:拼接字符串
拼接字符串使用静态方法
join()
,它用指定的字符串连接字符串数组:格式化字符串
字符串提供了
formatted()
方法和format()
静态方法,可以传入其他参数,替换占位符,然后生成新的字符串:占位符还可以带格式,例如
%.2f
表示显示两位小数。如果不确定用啥占位符,那就始终用
%s
,%s
可以显示任何数据类型。类型转换
要把任意基本类型或引用类型转换为字符串,可以使用静态方法
valueOf()
。这是一个重载方法,编译器会根据参数自动选择合适的方法:把字符串转换为其他类型:
Integer
有个getInteger(String)
方法,它不是将字符串转换为int
,而是把该字符串对应的系统变量转换为Integer
:转换为char[]
String
和char[]
类型可以互相转换,方法是:如果修改了
char[]
数组,String
并不会改变:这是因为通过
new String(char[])
创建新的String
实例时,它并不会直接引用传入的char[]
数组,而是会复制一份,所以,修改外部的char[]
数组不会影响String
实例内部的char[]
数组,因为这是两个不同的数组。从
String
的不变性设计可以看出,如果传入的对象有可能改变,我们需要复制而不是直接引用。例如,下面的代码设计了一个
Score
类保存一组学生的成绩:由于
Score
内部直接引用了外部传入的int[]
数组,这会造成外部代码对int[]
数组的修改,影响到Score
类的字段。如果外部代码不可信,这就会造成安全隐患。字符编码
在早期的计算机系统中,为了给字符编码,美国国家标准学会(American National Standard Institute:ANSI)制定了一套英文字母、数字和常用符号的编码,它占用一个字节,编码范围从
0
到127
,最高位始终为0
,称为ASCII
编码。例如,字符'A'
的编码是0x41
,字符'1'
的编码是0x31
。如果要把汉字也纳入计算机编码,很显然一个字节是不够的。
GB2312
标准使用两个字节表示一个汉字,其中第一个字节的最高位始终为1
,以便和ASCII
编码区分开。例如,汉字'中'
的GB2312
编码是0xd6d0
。类似的,日文有
Shift_JIS
编码,韩文有EUC-KR
编码,这些编码因为标准不统一,同时使用,就会产生冲突。为了统一全球所有语言的编码,全球统一码联盟发布了
Unicode
编码,它把世界上主要语言都纳入同一个编码,这样,中文、日文、韩文和其他语言就不会冲突。Unicode
编码需要两个或者更多字节表示,我们可以比较中英文字符在ASCII
、GB2312
和Unicode
的编码:英文字符
'A'
的ASCII
编码和Unicode
编码:英文字符的
Unicode
编码就是简单地在前面添加一个00
字节。中文字符
'中'
的GB2312
编码和Unicode
编码:那我们经常使用的
UTF-8
又是什么编码呢?因为英文字符的Unicode
编码高字节总是00
,包含大量英文的文本会浪费空间,所以,出现了UTF-8
编码,它是一种变长编码,用来把固定长度的Unicode
编码变成1~4字节的变长编码。通过UTF-8
编码,英文字符'A'
的UTF-8
编码变为0x41
,正好和ASCII
码一致,而中文'中'
的UTF-8
编码为3字节0xe4b8ad
。UTF-8
编码的另一个好处是容错能力强。如果传输过程中某些字符出错,不会影响后续字符,因为UTF-8
编码依靠高字节位来确定一个字符究竟是几个字节,它经常用来作为传输编码。在Java中,
char
类型实际上就是两个字节的Unicode
编码。如果要手动把字符串转换成其他编码,可以这样做:注意:转换编码后,就不再是
char
类型,而是byte
类型表示的数组。如果要把已知编码的
byte[]
转换为String
,可以这样做:Java的
String
和char
在内存中总是以Unicode编码表示对于不同版本的JDK,
String
类在内存中有不同的优化方式。早期JDK版本的String
总是以char[]
存储,定义如下:而较新的JDK版本的
String
则以byte[]
存储:如果String
仅包含ASCII字符,则每个byte
存储一个字符,否则,每两个byte
存储一个字符,这样做的目的是为了节省内存,因为大量的长度较短的String
通常仅包含ASCII字符:对于使用者来说,
String
内部的优化不影响任何已有代码,因为它的public
方法签名是不变的。