String详解

String介绍

String:字符串,使用一对””引起来表示

Java程序中的所有字符串字面值(如”abc”)都作为此类的实例实现

  1. String声明为final的,不可被继承,代表不可变的字符序列

  2. String实现了Serializable接口:表示字符串是支持序列化的

    实现了Comparable接口:表示String可以比较大小

  3. String内部定义了final char[] value用于存储字符串数据

  4. 4.String:代表不可变的字符序列。简称:不可变性

​ 体现:

  1. 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
  2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
  3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
  1. 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
  2. 字符串常量池中是不会存储相同内容的字符串的。
1
2
3
4
5
6
7
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0

String的实例化方式

​ 方式一:通过字面量定义的方式
​ 方式二:通过new + 构造器的方式

1
2
面试题:String s = new String("abc");方式创建对象,在内存中创建了几个对象?
两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
String s3 = new String("javaEE");
String s4 = new String("javaEE");

System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false

System.out.println("***********************");
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);

System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name == p2.name);//true

p1.name = "Jerry";
System.out.println(p2.name);//Tom

输出结果

1
2
3
4
5
6
7
8
true
false
false
false
***********************
true
true
Tom

String的特性

  1. 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
  2. 只要其中有一个是变量,结果就在堆中。
  3. 如果拼接的结果调用intern()方法,返回值就在常量池中
1
2
3
4
5
6
7
8
String s1 = "javaEEhadoop";
String s2 = "javaEE";
String s3 = s2 + "hadoop";
System.out.println(s1 == s3);//false

final String s4 = "javaEE";//s4:常量
String s5 = s4 + "hadoop";
System.out.println(s1 == s5);//true

输出结果

1
2
false
true

String使用陷阱

  • String s1 = “a”;

    说明:在字符串常量池中创建了一个字面量为”a”的字符串。

  • s1 = s1 + “b”;

    说明:实际上原来的“a”字符串对象已经丢弃了,现在在堆空间中产生了一个字符

    串s1+”b”(也就是”ab”)。如果多次执行这些改变串内容的操作,会导致大量副本

    字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响

    程序的性能。

  • String s2 = “ab”;

    说明:直接在字符串常量池中创建一个字面量为”ab”的字符串。

  • String s3 = “a” + “b”;

    说明:s3指向字符串常量池中已经创建的”ab”的字符串。

    String s4 = s1.intern();

    说明:堆空间的s1对象在调用intern()之后,会将常量池中已经存在的”ab”字符串

    赋值给s4。

String与基本类型、包装类之间的转换

String –> 基本数据类型、包装类:调用包装类的静态方法:parseXxx(str)
基本数据类型、包装类 –> String:调用String重载的valueOf(xxx)

1
2
3
4
5
6
7
String str1 = "123";
int num = Integer.parseInt(str1);

String str2 = String.valueOf(num);//"123"
String str3 = num + "";

System.out.println(str1 == str3);

输出结果:

1
true

String 与 char[]之间的转换

String –> char[]:调用String的toCharArray()
char[] –> String:调用String的构造器

1
2
3
4
5
6
7
8
9
10
String str1 = "abc123";  //题目: a21cb3

char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.print(charArray[i]);
}
System.out.println("------");
char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr);
System.out.println(str2);

输出结果

1
2
abc123------
hello

String 与 byte[]之间的转换

编码:String –> byte[]:调用String的getBytes()
解码:byte[] –> String:调用String的构造器

编码:字符串 –>字节 (看得懂 —>看不懂的二进制数据)
解码:编码的逆过程,字节 –> 字符串 (看不懂的二进制数据 —> 看得懂)

说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void test3() throws UnsupportedEncodingException {
String str1 = "abc123中国";
byte[] bytes = str1.getBytes();//使用默认的字符集,进行编码。
System.out.println(Arrays.toString(bytes));
byte[] gbks = str1.getBytes("gbk");//使用gbk字符集进行编码。
System.out.println(Arrays.toString(gbks));

System.out.println("******************");

String str2 = new String(bytes);//使用默认的字符集,进行解码
System.out.println(str2);

String str3 = new String(gbks);
System.out.println(str3);//出现乱码。原因:编码集和解码集不一致

String str4 = new String(gbks, "gbk");
System.out.println(str4);//没有出现乱码。原因:编码集和解码集一致
}

输出结果:

1
2
3
4
5
6
[97, 98, 99, 49, 50, 51, -28, -72, -83, -27, -101, -67]
[97, 98, 99, 49, 50, 51, -42, -48, -71, -6]
******************
abc123中国
abc123�й�
abc123中国

String的常用方法

  • int length():返回字符串的长度: return value.length

  • char charAt(int index): 返回某索引处的字符return value[index]

  • boolean isEmpty():判断是否是空字符串:return value.length == 0

  • String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写

  • String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写

  • String trim():返回字符串的副本,忽略前导空白和尾部空白

1
2
3
4
5
6
7
8
9
10
11
12
13
14
String s1 = "HelloWorld";
System.out.println(s1.length());
System.out.println(s1.charAt(0));
System.out.println(s1.charAt(9));
System.out.println(s1.isEmpty());

String s2 = s1.toLowerCase();
System.out.println(s1);//s1不可变的,仍然为原来的字符串
System.out.println(s2);//改成小写以后的字符串

String s3 = " he llo world ";
String s4 = s3.trim();
System.out.println("-----" + s3 + "-----");
System.out.println("-----" + s4 + "-----");

输出结果:

1
2
3
4
5
6
7
8
10
H
d
false
HelloWorld
helloworld
----- he llo world -----
-----he llo world-----
  • boolean equals(Object obj):比较字符串的内容是否相同

  • boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写

  • String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”

  • int compareTo(String anotherString):比较两个字符串的大小

  • String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。

  • String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
String s1 = "HelloWorld";
String s2 = "helloworld";
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));

String s3 = "abc";
String s4 = s3.concat("def");
System.out.println(s4);

String s5 = "abc";
String s6 = new String("abe");
System.out.println(s5.compareTo(s6));//涉及到字符串排序

String s7 = "爱吃鱼的呆先生";
String s8 = s7.substring(2);
System.out.println(s7);
System.out.println(s8);

String s9 = s7.substring(2, 5);
System.out.println(s9);

输出结果:

1
2
3
4
5
6
7
false
true
abcdef
-2
爱吃鱼的呆先生
鱼的呆先生
鱼的呆
  • boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束

  • boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始

  • boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始

  • boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true

  • int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引

  • int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始

  • int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引

  • int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索

注:indexOf和lastIndexOf方法如果未找到都是返回-1

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 = "hellowworld";
boolean b1 = str1.endsWith("rld");
System.out.println(b1);

boolean b2 = str1.startsWith("He");
System.out.println(b2);

boolean b3 = str1.startsWith("ll",2);
System.out.println(b3);

String str2 = "wor";
System.out.println(str1.contains(str2));

System.out.println(str1.indexOf("lol"));

System.out.println(str1.indexOf("lo",5));

String str3 = "hellorworld";

System.out.println(str3.lastIndexOf("or"));
System.out.println(str3.lastIndexOf("or",6));

//什么情况下,indexOf(str)和lastIndexOf(str)返回值相同?
//情况一:存在唯一的一个str。情况二:不存在str

输出结果:

1
2
3
4
5
6
7
8
true
false
true
true
-1
-1
7
4

替换:

  • String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
  • String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
  • String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
  • String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

匹配:

  • boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。

切片:

  • String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
  • String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
String str1 = "爱吃鱼的呆先生";
String str2 = str1.replace('北', '东');

System.out.println(str1);
System.out.println(str2);


String str3 = str1.replace("北京", "上海");
System.out.println(str3);

System.out.println("*************************");
String str = "12hello34world5java7891mysql456";
//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string);

System.out.println("*************************");
str = "12345";
//判断str字符串中是否全部有数字组成,即有1-n个数字组成
boolean matches = str.matches("\\d+");
System.out.println(matches);
String tel = "0571-4534289";
//判断这是否是一个杭州的固定电话
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result);


System.out.println("*************************");
str = "hello|world|java";
String[] strs = str.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
System.out.println();
str2 = "hello.world.java";
String[] strs2 = str2.split("\\.");
for (int i = 0; i < strs2.length; i++) {
System.out.println(strs2[i]);
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
爱吃鱼的呆先生
爱吃鱼的呆先生
爱吃鱼的呆先生
*************************
hello,world,java,mysql
*************************
true
true
*************************
hello
world
java

hello
world
java
文章目录
  1. 1. String介绍
  2. 2. String的实例化方式
  3. 3. String的特性
    1. 3.1. String使用陷阱
  4. 4. String与基本类型、包装类之间的转换
  5. 5. String 与 char[]之间的转换
  6. 6. String 与 byte[]之间的转换
  7. 7. String的常用方法
|