Java 中的字符串详解

String 类

声明字符串

字符串是常量,它们可以显示任何文本信息,字符串的值在创建之后不能更改。在 Java 语言中,单引号中的内容表示字符,例如 's',而双引号中的内容则表示字符串,例如"这是一段字符串"

Java 通过 java.lang.String 这个类来创建可以保存字符串的变量,所以字符串变量是一个对象。

声明一个字符串变量 a ,以及声明两个字符串变量 a、b 代码如下:

1
2
String a;
String a, b;

PS:在不给字符串赋值的情况下,默认值为 null,也就是空对象,如果此时调用 String 的方法就会发生空指针异常:java.lang.NullPointerException

创建字符串

引用字符串常量

直接将字符串常量赋值给 String 类型变量,例如:

1
2
3
4
5
String a = "时间就金钱";
String b = "锄禾日当午", c = "汗滴禾下土";
String d, e;
d = "We are students";
e = "We are students";

当两个字符串对象引用相同的常量时,就具有相同的实体。

利用构造方法实例化

使用 new 关键字创建 String 对象,例如:

1
2
3
4
5
String a = new String("使用 new 关键字创建对象");
String b = new String(a);

System.out.println(a);// 输出:使用 new 关键字创建对象
System.out.println(b);// 输出:使用 new 关键字创建对象

利用字符组实例化

定义一个字符数组 charArray,使用该字符数组创建一个字符串,例如:

1
2
3
4
char[] charArray = {'t', 'i', 'm', 'e'};
String a = new String(charArray);

System.out.println(a);// 输出:time

提取字符数组中的一部分创建字符串对象

定义一个字符数组 charArray,从该字符数组索引 3 的位置开始,提取两个元素,创建一个字符串,例如:

1
2
3
4
char[] charArray = {'时', '间', '就', '是', '金', '钱'};
String a = new String(charArray, 3, 2);

System.out.println(a);// 输出:金钱

连接字符串

连接字符串

使用 + 运算符可以实现拼接多个字符串的功能,+ 运算符可以连接多个字符串并产生一个新的 String 对象。除了 + 运算符,+= 同样可以实现字符串的拼接,例如

1
2
3
4
5
6
7
8
9
10
String a = "abc";
String b = "123";
String c = a + b;
String d = "拼接字符串";
d += c;

System.out.println(a);// 输出:abc
System.out.println(b);// 输出:123
System.out.println(c);// 输出:abc123
System.out.println(d);// 输出:拼接字符串abc123

PS:Java 中相连的字符串不可以直接分成两行,例如:

1
2
String a = "This is
a String";

这种写法是错误的,如果一个字符串太长,为了方便阅读,可以将这个字符串分在两行上书写。此时就可以用 + 将两个字符串连接起来,之后在 + 处换行,上面的语句可以修改为:

1
2
String a = "This is" +
"a String";

PS:使用 String 类的 concat() 方法也可以实现将制定字符串连接到此字符串结尾的功能,这个方法后面再详细讲。

连接其他数据类型

字符串也可同其他基本数据类型进行连接。如果将字符串同这些数据类型进行连接,会将这些数据类型直接转换成字符串,例如:

1
2
3
4
int booktime = 4;
float practice = 2.5f;
String str = "我每天花费" + booktime + "小时看书," + practice + "小时上机练习";
System.out.println(str);// 输出:我每天花费4小时看书,2.5小时上机练习

本例实现的是将字符串于整形变量 booktime 和浮点类型变量 practice 相连后的结果输出。在这里 booktime 和 practice 都不是字符串,当它们与字符串相连时会自动调用 toString() 方法,将其转换为字符串形式,然后参与连接,toString() 方法后面再详细讲。

String 类中的方法详解

charAt(int index)

public char charAt(int index)

可以将指定索引处的字符串返回,其中 index 的取值范围为 0 至 length() - 1,例如:

1
2
3
String str = "床前明月光,疑是地上霜。";
char chr = str.charAt(4);
System.out.println(chr);// 输出:光

codePointAt(int index)

public int codePointAt(int index)

可以返回指定索引处的字符的 Unicode 码,其中 index 的取值范围为 0 至 length() - 1,例如:

1
2
3
String str = "abcde";
int i = str.codePointAt(3);
System.out.println(chr);// 输出:100(d 的 Unicode 值)

codePointBefore(int index)

public int codePointBefore(int index)

可以返回指定索引(index -1)处的字符的 Unicode 码,其中 index 的取值范围为 1 至 length(),例如:

1
2
3
String str = "abcde";
int i = str.codePointBefore(3);
System.out.println(chr);// 输出:99(c 的 Unicode 值)

compareTo(String anotherString)

public int compareTo(String anotherString)

按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。将此 String 对象表示的字符序列与参数字符串所表示的字符序列进行比较。如果按字典顺序此 String 对象在参数字符串之前,则比较结果为一个负整数。如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。如果这两个字符串相等,则结果为 0;compareTo() 只有在方法 equals(Object) 返回 true 时才返回 0。

1
2
3
4
5
6
7
8
9
10
String s = "s";
String a = "a";
String b = "s";
String c = "z";
int x = a.compareTo(s);
int y = b.compareTo(s);
int z = c.compareTo(s);
System.out.println(x);// 输出:-18  a = 97, s = 115, 97 - 115 = -18
System.out.println(y);// 输出:0  s = 115, 115 - 115 = 0
System.out.println(z);// 输出:7  z = 122, s = 115, 122 - 115 = 7

compareToIgnoreCase(String str)

public int compareToIgnoreCase(String str)

比较方式同上面的 compareTo,不过忽略大小写,例如:

1
2
3
4
String a = "A";
String b = "a";
int x = a.compareToIgnoreCase(b);
System.out.println(x);// 输出:0

concat(String str)

public String concat(String str)

将指定的字符串连接到该字符串的末尾,例如:

1
2
3
4
String a = "abc";
String b = "123";
String c = a.concat(b);// 其中 a 和 b 均不能为 null
System.out.println(c);// 输出:abc123

contains(CharSequence s)

public boolean contains(CharSequence s)

当该字符串包含指定的字符或字符串时返回 true 否则返回 false,例如:

1
2
3
4
5
String a = "abc";
boolean m = a.contains("a");
boolean n = a.contains("ac");
System.out.println(m);// 输出:true
System.out.println(n);// 输出:false

copyValueOf(char[] data)

public static String copyValueOf(char[] data)

相当于 valueOf(char[]),将一个 char 数组转换为一个字符串,例如:

1
2
3
char[] c = new char[]{'t', 'i', 'm', 'e'};
String a = String.copyValueOf(c);
System.out.println(a);// 输出:time

copyValueOf(char[] data, int offset, int count)

public static String copyValueOf(char[] data, int offset, int count)

相当于 valueOf(char[], int, int),返回从 data 中截取以 offset 开始的长度为 count 的字符串,例如:

1
2
3
char[] c = new char[]{'t', 'i', 'm', 'e'};
String a = String.copyValueOf(c, 1, 3);
System.out.println(a);// 输出:ime

如果 offset 为负数,或 count 为负数,或 offset + count 大于 data.length, 会抛出 java.lang.IndexOutOfBoundsException 异常。

endsWith(String suffix)

public boolean endsWith(String suffix)

如果该字符串以 suffix 结尾或传入空字符串或其本身则返回 true,否则返回 false,例如:

1
2
3
4
5
6
7
8
9
String s = "test.txt";
boolean a = s.endsWith("");
boolean b = s.endsWith(s);
boolean c = s.endsWith(".txt");
boolean d = s.endsWith(".pdf");
System.out.println(a);// 输出:true
System.out.println(b);// 输出:true
System.out.println(c);// 输出:true
System.out.println(d);// 输出:false

equals(Object anObject)

public boolean equals(Object anObject)

将此字符串于指定的对象比较,当该参数不为 null,并且是与此对象表示相同的字符序列的 String 对象时才会返回 true,否则返回 false,除了 equals(Object anObject) 方法外,== 也可以比较字符串,不过 == 比较的是两者的内存地址是否相同,通常比较两个字符串对象的内容是否相同用 equals(Object anObject)equalsIgnoreCase(String anotherString),不用 ==,例如:

1
2
3
4
5
6
7
8
9
10
11
12
String a = "abc";
String b = new String("abc");
String c = new String("123");
String d = b;
System.out.println(a == b);// 输出:false
System.out.println(a == c);// 输出:false
System.out.println(a == d);// 输出:false
System.out.println(b == d);// 输出:true
System.out.println(a.equals(b));// 输出:true
System.out.println(a.equals(c));// 输出:false
System.out.println(a.equals(d));// 输出:true
System.out.println(b.equals(d));// 输出:true

equalsIgnoreCase(String anotherString)

public boolean equalsIgnoreCase(String anotherString)

equals(Object anObject) 类似,将此字符串对象与指定的字符串对象比较,不考虑大小写,如果两个字符串的长度相同,并且两个字符串对象中的相应字符都相等,则两个字符串被认为是相等的,例如:

1
2
3
4
String a = "abc";
String b = "ABC";
System.out.println(a.equals(b));// 输出:false
System.out.println(a.equalsIgnoreCase(b));// 输出:true

format(Locale l, String format, Object… args)

public static String format(Locale l, String format, Object... args)

  • l:格式化过程中要应用的语言环境,如果 l 为 null,则不进行本地化。
  • format:格式字符串。
  • args:格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,则忽略这些额外参数。此参数的数目是可变的,可以为 0。

使用方法参考下面的 format(String format, Object... args)

format(String format, Object… args)

public static String format(String format, Object... args)

  • format:格式字符串。
  • args:格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,则忽略这些额外参数。此参数的数目是可变的,可以为 0。
日期时间字符串格式化
日期格式化

格式化获取年份示例代码:

1
2
3
java.util.Date d = new java.util.Date();
String y = String.format("%tY",d);
System.out.println(y);// 输出:2017

上面的 %tY 为转换符,区分大小写,表示 4 位年份,常见的日期格式转换符如下表所示:

转换符 说明 示例
%ta 指定语言环境的星期几简称 Tues(英文)、星期二(中文)
%tA 指定语言环境的星期几全称 Tuesday(英文)、星期二(中文)
%tb 指定语言环境的月份简称 Nov(英文)、十一月(中文)
%tB 指定语言环境的月份全称 November(英文)、十一月(中文)
%tc 包括全部日期和时间信息 星期二 十一月 21 21:57:47 CST 2017
%td 一个月中的第几天(01~31) 21
%te 一个月中的某一天(1~31) 21
%tj 一年中的第几天(001~366) 325
%tm 月份 11
%ty 2位年份 17
%tY 4位年份 2017
时间格式化

格式化获取当前时间示例代码:

1
2
3
4
5
java.util.Date d = new java.util.Date();
String h = String.format("%tH", d);
String m = String.format("%tM", d);
String s = String.format("%tS", d);
System.out.println(h + ":" + m + ":" + s);// 输出:22:17:16

使用 format() 方法不仅可以完成日期的格式化,也可以用来实现时间的格式化。常见的时间格式化转换符如下表所示:

转换符 说明 示例
%tH 2 位数的 24 时制的小时(00~23) 22
%tI 2 位数的 12 时制的小时(01~12) 10
%tk 1~2 位数字的 24 时制的小时(0~23) 22
%tl 1~2 位数字的 12 时制的小时(1~12) 10
%tM 2 位数字的分钟(00~59) 09
%tS 2 位数字的秒数(00~60) 05
%tL 3 位数字的毫秒数(000~999) 732
%tN 9 位数字的微秒数(000000000~999999999) 624000000
%tp 指定语言环境上午或下午 下午
%tz 相对于 GMT RFC 82 格式的数字失去偏移量 +0800
%tZ 时区缩写形式的字符串 CST
%ts 1970-01-01 00:00:00 至现在经过的秒数 1511273666
%tQ 1970-01-01 00:00:00 至现在经过的毫秒数 1511273678532
格式化常见的日期时间组合

格式化获取当前日期和时间组合示例代码:

1
2
3
4
5
6
7
java.util.Date d = new java.util.Date();
String c = String.format("%tc", d);
String D = String.format("%tD", d);
String F = String.format("%tF", d);
System.out.println(c);// 输出:星期二 十一月 21 22:20:27 CST 2017
System.out.println(D);// 输出:11/21/17
System.out.println(F);// 输出:2017-11-21

格式化日期与时间的转换符定义了各种日期时间的组合格式,其中最常用的日期和时间格式如下表所示:

转换符 说明 示例
%tc 全部日期和时间信息 星期二 十一月 21 22:20:27 CST 2017
%tD 「月/日/年」格式(2 位年份) 11/21/17
%tF 「月-日-年」格式(4 位年份) 2017-11-21
%tr 「时:分:秒 PM(AM)」格式(12时制) 10:27:36 下午
%tR 「时:分」格式(24时制) 22:27
%tT 「时:分:秒」格式(24时制) 22:28:22
常规类型格式化

常规类型格式化示例代码:

1
2
3
4
5
6
7
8
9
System.out.println(String.format("%a", 16.0));// 输出:0x1.0p4
System.out.println(String.format("%b", 0 < 1));// 输出:true
System.out.println(String.format("%b", 0 > 1));// 输出:false
System.out.println(String.format("%d", 10 + 6));// 输出:16
System.out.println(String.format("%e", 1000000.16));// 输出:1.000000e+06
System.out.println(String.format("%.2f", Math.PI));// 输出:3.14
System.out.println(String.format("%h", 196));// 输出:c4
System.out.println(String.format("%o", 16));// 输出:20
System.out.println(String.format("%x", 16));// 输出:10

常规类型的格式转化可应用于任何参数类型,常见的格式化转换符如下表所示:

转换符 说明 示例
%a 结果被格式化为带有效位数和指数的十六进制浮点值 0x1.0p4
%b、%B 结果被格式化为布尔类型 true
%c、%C 结果被格式化为字符类型 ‘z’
%d 结果被格式化为十进制整数 16
%e 结果被格式化为用计算机科学计数法表示的十进制数 1.000000e+06
%f 结果被格式化为小数点后指定位数的小数 3.14
%h、%H 结果被格式化为散列码 c4
%n 结果为特定于平台的行分隔符  
%o 结果被格式化为八进制整数 20
%s、%S 结果被格式化为字符串类型 “zpp0196”
%x、%X 结果被格式化为十六进制整数 10
%% 结果为字面值 % %

使用转换符,还可以配合转换符标识来控制输出的格式,常见的转换符标识如下表所示:

标识 说明 示例
’+’ 显示数字的正负号 +16
’-‘ 在最小宽度内左对齐,不可以于 ‘0’ 填充标识同时使用 .16 .
’#’ 用于 8 进制和 16 进制格式,在 8 进制前加一个 ’0‘ ,在 16 进制前加一个 ’0x‘ 0x10
’ ‘ 在正数前加空格,在负数前面加 ’-‘ -16
‘0’ 在不够最小位数的结果前用 0 填充 00016
’,’ 只适用于10进制,每三位数字用 ‘,’ 分割 794,970,247
’(‘ 用括号把负数括起来 (16)

使用转换符标识来控制输出的格式示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
String str1 = String.format("%5d", 123);// 让字符串的最大长度为 5,不足长度在前段补空格
System.out.println("|" + str1 + "|");// 输出:|  123|
String str2 = String.format("%-5d", 123);// 让字符串左对齐
System.out.println("|" + str2 + "|");// 输出:|123  |
String str3 = String.format("%#o", 16);// 在 8 进制前面加一个 0
System.out.println(str3);// 输出:020
String str4 = String.format("%#x", 16);// 在 16 进制前面加一个 0x
System.out.println(str4);// 输出:0x10
String str5 = String.format("%+d", 16);// 让数字显示正负号
System.out.println(str5);// 输出:+16
String str6 = String.format("%+d", -16);// 让数字显示正负号
System.out.println(str6);// 输出:-16
String str7 = String.format("% d", 16);// 在正数前面补一个空格
System.out.println("|" + str7 + "|");// 输出:| 16|
String str8 = String.format("% d", -16);// 在负数前面补一个负号
System.out.println("|" + str8 + "|");// 输出:|-16|
String str9 = String.format("%05d", 16);// 让字符串的最大长度为 5,不足长度在前段补 0
System.out.println(str9);// 输出:00016
String str10 = String.format("%,d", 794970247);
System.out.println(str10);// 输出:794,970,247
String str11 = String.format("%(d", 16);// 正数无影响
System.out.println(str11);// 输出:16
String str12 = String.format("%(d", -16);// 负数用括号括起来
System.out.println(str12);// 输出:(16)

如果格式字符串包含非法语法,则与给定参数不兼容的格式说明符,给定格式字符串的参数不足或其他非法条件会抛出异常 java.util.IllegalFormatException

getBytes()

public byte[] getBytes()

将一个字符串对象转化为一个字节数组 byte[],例如:

1
2
3
4
5
String a = "abc";
byte[] b = a.getBytes();
System.out.println(b[0]);// 输出:97
System.out.println(b[1]);// 输出:98
System.out.println(b[2]);// 输出:99

getBytes(Charset charset)

public byte[] getBytes(Charset charset)

将此字符串对象使用给定的字符集的字节序列解码,并将结果存储到一个新的字节数组,例如:

1
2
3
4
5
6
7
8
9
10
11
try{
    String s = "嗨";
    byte[] m = s.getBytes("utf-8");
    byte[] n = s.getBytes("ISO8859-1");
    String x = new String(m, "utf-8");
    String y = new String(n, "ISO8859-1");
    System.out.println(x);// 输出:嗨
    System.out.println(y);// 输出:?
}catch(UnsupportedEncodingException e){
    e.printStackTrace();
}

getBytes(String charsetName)

public byte[] getBytes(String charsetName) throws UnsupportedEncodingException

将此字符串对象使用给定的字符集的字节序列编码,并将结果存储到一个新的字节数组,例如:

1
2
3
4
5
6
7
8
9
try{
    String s = "abc";
    byte[] b = s.getBytes("utf-8");
    System.out.println(b[0]);// 输出:97
    System.out.println(b[1]);// 输出:98
    System.out.println(b[2]);// 输出:99
}catch(UnsupportedEncodingException e){
    e.printStackTrace();
}

如果不支持指定的字符集则会抛出 java.io.UnsupportedEncodingException异常。

getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

  • srcBegin:这是复制的字符串的第一个字符的索引。
  • srcEnd:这是复制字符串中的最后一个字符之后的索引。
  • dst:这是目标数组。
  • dstBegin:这是一开始的目标数组中的偏移量。

复制此字串到目标字符数组的字符,例如:

1
2
3
4
5
6
String a = "时间就是金钱";
char[] c = new char[3];
a.getChars(4, 6, c, 1);
System.out.println(c[0]);// 输出:
System.out.println(c[1]);// 输出:金
System.out.println(c[2]);// 输出:钱

如果 以下条件为成立则会抛出 java.lang.IndexOutOfBoundsException 异常:

  • srcBegin < 0
  • srcBegin > srcEnd
  • srcEnd > 此字符串的长度
  • dstBegin < 0
  • dstBegin + (srcEnd - srcBegin) > dst.length

hashCode()

public int hashCode()

返回此字符串对象的哈希码。字符串对象的哈希代码计算公式为: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 其中,s[i]为字符串的第i个字符,n是字符串的长度,^表示求幂,例如:

1
2
String a = "zpp0196";
System.out.println(a.hashCode());// 输出:-82322472

暂时先写这么多,除了 String 类还有 StringBuffer 和 StringBuilder,后面再慢慢更新,最后编辑于 2017年11月22日00:31。