5 字符串
java.lang.String
类代表字符串。Java程序中所有的字符串文字(例如"abc"
)都可以被看作是实现此类的实例。字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。
String
类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。
Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持(toString()方法)。
5.1 字符串的特点
1、字符串String类型本身是final声明的,意味着我们不能继承String。
2、字符串的对象也是不可变对象,意味着一旦进行修改,就会产生新对象
我们修改了字符串后,如果想要获得新的内容,必须重新接受。
如果程序中涉及到大量的字符串的修改操作,那么此时的时空消耗比较高。可能需要考虑使用StringBuilder或StringBuffer的可变字符序列。
3、String对象内部是用字符数组进行保存的
JDK1.9之前有一个char[] value数组,JDK1.9之后byte[]数组
"abc"
等效于 char[] data={ 'a' , 'b' , 'c' }
。
例如:
String str = "abc";
相当于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
// String底层是靠字符数组实现的。
4、String类中这个char[] values数组也是final修饰的,意味着这个数组不可变,然后它是private修饰,外部不能直接操作它,String类型提供的所有的方法都是用新对象来表示修改后内容的,所以保证了String对象的不可变。
5、就因为字符串对象设计为不可变,那么所以字符串有常量池来保存很多常量对象
常量池在方法区。
如果细致的划分:
(1)JDK1.6及其之前:方法区
(2)JDK1.7:堆
(3)JDK1.8:元空间
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
// 内存中只有一个"abc"对象被创建,同时被s1和s2共享。
5.2 构造字符串对象
1、使用构造方法
-
public String()
:初始化新创建的 String对象,以使其表示空字符序列。 -
String(String original)
: 初始化一个新创建的String
对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。 -
public String(char[] value)
:通过当前参数中的字符数组来构造新的String。 -
public String(char[] value,int offset, int count)
:通过字符数组的一部分来构造新的String。 -
public String(byte[] bytes)
:通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。 -
public String(byte[] bytes,String charsetName)
:通过使用指定的字符集解码当前参数中的字节数组来构造新的String。
构造举例,代码如下:
//字符串常量对象
String str = "hello";
// 无参构造
String str1 = new String();
//创建"hello"字符串常量的副本
String str2 = new String("hello");
//通过字符数组构造
char chars[] = {'a', 'b', 'c','d','e'};
String str3 = new String(chars);
String str4 = new String(chars,0,3);
// 通过字节数组构造
byte bytes[] = {97, 98, 99 };
String str5 = new String(bytes);
String str6 = new String(bytes,"GBK");
2、使用静态方法
-
static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String
-
static String copyValueOf(char[] data, int offset, int count):返回指定数组中表示该字符序列的 String
-
static String valueOf(char[] data) : 返回指定数组中表示该字符序列的 String
-
static String valueOf(char[] data, int offset, int count) : 返回指定数组中表示该字符序列的 String
-
static String valueOf(xx value):xx支持各种数据类型,返回各种数据类型的value参数的字符串表示形式。
public static void main(String[] args) {
char[] data = {'h','e','l','l','o','j','a','v','a'};
String s1 = String.copyValueOf(data);
String s2 = String.copyValueOf(data,0,5);
int num = 123456;
String s3 = String.valueOf(num);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
3、使用""+
任意数据类型与"字符串"进行拼接,结果都是字符串
public static void main(String[] args) {
int num = 123456;
String s = num + "";
System.out.println(s);
Student stu = new Student();
String s2 = stu + "";//自动调用对象的toString(),然后与""进行拼接
System.out.println(s2);
}
5.3 字符串的对象的个数
1、字符串常量对象
String str1 = "hello";//1个,在常量池中
2、字符串的普通对象和常量对象一起
String str3 = new String("hello");
//str3首先指向堆中的一个字符串对象,然后堆中字符串的value数组指向常量池中常量对象的value数组
5.4 字符串对象的内存分析
String s;
String s = null;
String s = "";
String s = new String();
String s = new String("");
String s = "abc";
String s = new String("abc");
char[] arr = {'a','b'};
String s = new String(arr);
char[] arr = {'a','b','c','d','e'};
String s = new String(arr,0,3);
5.5 字符串拼接问题
1、拼接结果的存储和比较问题
原则:
(1)常量+常量:结果是常量池
(2)常量与变量 或 变量与变量:结果是堆
(3)拼接后调用intern方法:结果在常量池