String
1 不可变特性
String类表示字符串,字符串是不可变的,他们的值在创建后就无法更改。例如:
String str = "abc";
相当于
char data[] = {'a','b','c'}; //因为数组一经创建,其大小是不能更改的,所以字符串也就不能更改了
String str = new String(data);
2 共享性
字符串是不可变类。如果两个字符串对象通过直接赋值的方法创建且内容完全一致,则他们地址也是相同的(== 结果为true)。例如:
String s1 = "abcd";
String s2 = "abcd";
System.out.println(s1 == s2);
//结果为true
因为这个特性,String类的对象是被共享的,它有一个字符串常量池位于方法区中;方法区是被所有线程共享的,该区域存储的还有 静态变量 、常量、类信息(构造方法/接口定义)+ 运行时常量池。
注意:
如果字符串对象是通过 new
关键字创建的,那么即使两个对象内容相同,他们的地址也是不同的。例如:
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //true
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s3 == s4); //false
System.out.println(s1 == s3); //false
System.out.println(s1 == s4); //false
3 堆空间
一个JVM只存在一个堆内存,当前高版本JDK不需要我们进行调节其大小。类加载器读取了文件之后,需要把类、方法,常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器操作。
堆在逻辑上分为三个部分:
-
新生代(YoungGen)
存储新创建的对象。在这里垃圾回收比较频繁,如果一个对象经过15次垃圾回收都还未被回收,则会把该对象移到老年代区。
-
老年代(OldGen)
垃圾回收频率较新生代区域低很多。
-
永久代(PermGen)
存储在永久代区域的信息不会被垃圾回收,被
static
修饰的方法或者变量都会存放到此处,同时,String
对象也是存储在本区域。对于每次通过赋值创建
String
的对象,系统都会先找永久代中是否已经存在相同对象,如果有,则共享同一对象,这也是上述 共享性 的原因。
4 字符串拼接
使用 +
对String字符串进行拼接是非常耗内存的,每一次 +
运算就会产生一个新的字符串,这些字符串就会被存储在字符串常量池中不被回收,而产生的这些中间字符串是我们所不需要的,这就造成了内存的浪费。
需要进行字符串拼接时,建议使用 StringBuffer或者StringBuilder
.StringBuffer线程安全,类似于多个人排队吃一碗饭;StringBuilder线程不安全,类似于多个人同时吃一碗饭。
5 字符串常用方法
方法 | 作用 |
---|---|
charAt(int index) | 返回index下标的值 |
codePointAt(int index) | 返回index下标的Unicode值 |
compareTo(String s2) | 按照字典顺序比较两个字符串大小 |
contains(char c) | 如果字符串包含字符c,则返回true |
equals(Object o) | 与指定对象进行比较 |
getBytes() | 返回平台默认的字符集编码为字节序列返回 |
indexOf(Object o) | 返回对象o在字符串中的下标 |
isEmpty() | 判断是否为空 |
length() | 返回字符串长度 |
replace(char oldChar, char newChar) | 把字符串中的oldChar替换为newChar |
split(String regex) | 将字符串以给定分隔符进行拆分 |
strip() | 去除字符串头和尾部的空格 |
trim() | 去除所有头部和尾部的空格 |
toLowerCase() | 将字符串全部转换为小写 |
valueOf(Object o) | 返回对象o的字符串表示形式 |