String的特性
- String类: 代表字符串。 Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现
- String是一个final类,代表不可变的字符序列
- 字符串是常量,用双引号引起来表示。 它们的值在创建之后不能更改
- String对象的字符内容是存储在一个字符数组value[]中的
不可变的好处
1.可以缓存 hash 值
因为 String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。
2. String Pool 的需要
如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。
3. 安全性
String 经常作为参数,String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中,String 被改变,改变 String 的那一方以为现在连接的是其它主机,而实际情况却不一定是。
4. 线程安全
String 不可变性天生具备线程安全,可以在多个线程中安全地使用。
String常用方法
String与基本数据类型的转换
字符串 -> 基本数据类型、包装类
Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
类似地,使用java.lang包中的Byte、 Short、 Long、 Float、 Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型
基本数据类型、包装类 -> 字符串
调用String类的public String valueOf(int n)可将int型转换为字符串
相应的valueOf(byte b)、 valueOf(long l)、 valueOf(float f)、 valueOf(double d)、 valueOf(boolean b)可由参数的相应类型到字符串的转换
@Test
public void StringTest2(){
String str = "1";
int i;
long l;
short s;
byte b;
float f;
double d;
i = Integer.parseInt(str);
l = Long.parseLong(str);
s = Short.parseShort(str);
b = Byte.parseByte(str);
f = Float.parseFloat(str);
d = Double.parseDouble(str);
str = String.valueOf(i);
str = String.valueOf(l);
str = String.valueOf(s);
str = String.valueOf(b);
str = String.valueOf(f);
str = String.valueOf(d);
String str1 = “abc”;与String str2 = new String(“abc”);的区别?
- 字符串常量存储在字符串常量池, 目的是共享
- 字符串非常量对象存储在堆中。
因此就有
@Test
public void StringTest(){
String a = "hello";
String b = new String("hello");
System.out.println(a == b); // false,string是一个引用类型,使用==比较的是地址,a是在常量池中开辟的内存,而b是在堆中开辟的内存
System.out.println(a.equals(b)); // true,equal比较的是值
}
String Pool
字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。
当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。
下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得同一个字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中,然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。
String s1 = new String("aaa");
String s2 = new String("aaa");
System.out.println(s1 == s2); // false
String s3 = s1.intern();
String s4 = s1.intern();
System.out.println(s3 == s4); // true
如果是采用 “bbb” 这种字面量的形式创建字符串,会自动地将字符串放入 String Pool 中。
String s5 = "bbb";
String s6 = "bbb";
System.out.println(s5 == s6); // true
StringBuffer
- java.lang.StringBuffer代表可变的字符序列
- 很多方法与String相同。
- 作为参数传递时,方法内部可以改变值。
StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:
- StringBuffer():初始容量为16的字符串缓冲区
- StringBuffer(int size):构造指定容量的字符串缓冲区
- StringBuffer(String str):将内容初始化为指定字符串内容
StringBuilder类
StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列, 而且提供相关功能的方法也一样
String StringBuffer StingBuilder的区别
- String(JDK1.0): 不可变字符序列
- StringBuffer(JDK1.0): 可变字符序列、效率低、线程安全
- StringBuilder(JDK 5.0):可变字符序列、效率高、 线程不安全
注意:作为参数传递的话,方法内部String不会改变其值, StringBuffer和StringBuilder会改变其值。
@Test
public void StringTest3(){
String s = "123456";
StringBuffer sb = new StringBuffer("123456");
StringBuilder sbd = new StringBuilder("123456");
strChange(s);
strChange(sb);
strChange(sbd);
System.out.println(s);
System.out.println(sb);
System.out.println(sbd);
}
public void strChange(String str){
str.replace("1","3");
}
public void strChange(StringBuffer str){
str.replace(0,1,"3");
}
public void strChange(StringBuilder str){
str.replace(0,1,"3");
}
输出
123456
323456
323456