首页 > 代码库 > String
String
String
一、构造方式
两种构造方式
String str1 = "abc" ; String str2 = new String("abc");
2. 两种比较方式
== 基本数据类型,比较大小;引用数据类型,比较栈中存储的堆中开辟的地址的首地址是否相同
equals 仅限于引用数据类型;对于 Object 类型数据,功能同 == 比较的是内存空间的地址,其他 重写了 Object 的 equals 方法的类,则是比较对象的内容。
// 声明两个Object 对象 Object obj1 = new Object(); Object obj2 = new Object(); // 结果为false ,此时的equals 与 == 比较的相同,都是比较地址 System.out.println(obj1.equals(obj2));
// Object 类中的 equals 源码 public boolean equals(Object obj) { return (this == obj); // 与 == 相同 }
3. 第一种构造方式
java 中 String 类型有字符串常量池,即缓冲池机制,在构造字符串时,会先去缓冲池中查找是否有相同的内容,如果有则直接返回;如果没有,则创建一个新的放入缓冲池中,再返回。
所以,通过此种方式构造的字符串,只要内容相同,其内存地址一定相同。
String str1 = "abc" ; String str3 = "abc" ; System.out.println( str1 == str3); // true System.out.println(str1.equals(str3)); // true
4.第二种构造方式
new 在堆中开辟一块新的空间
String str2 = new String("abc"); String str4 = new String("abc"); System.out.println(str2 == str4); // 新开辟的两个空间地址一定不等,false System.out.println(str2.equals(str4)); // true
String str = new String("abc");
(1) "abc" 在堆中开辟空间,存放 abc ,匿名对象,栈中无句柄指向此空间
"abc".equals(str); // 对象调用类中的方法,此时"abc"是一个匿名对象
(2) new String("abc") 在堆中开辟新的空间,内容为 abc
(3) 栈中建立 str2 ,句柄指向 new String("abc") 开辟的空间的首地址,并存储该地址
(4) 匿名空间由于无句柄指向,等待GC回收
(5) 构造方法赋值的对象内容不放入缓冲池中
(6)
String str1 = "abc" ; String str2 = new String("abc"); // 若 abc 的匿名对象已存在,则无需再次创建;则此时只需新开辟一次空间
(7)此种方式创建对象共需要开辟几次空间
取决于匿名的字符串对象"abc" 是否已存在,若不存在,则为两次;否则,则为一次
5.总结
构造字符串时优先考虑第一中方式,可重复利用;第二种方式两次开辟内存空间
二、String
String 类不可继承
String 类实现序列化接口、比较器接口
// final 修饰,此类不可继承 public final class String implements java.io.Serializable, Comparable<String>, CharSequence
三、String内容不可变
// 存储内容实际为 char类型的数据,为final 修饰 /** The value is used for character storage. */ private final char value[];
四、字符串拼接
String str = 字符串常量 或 匿名的字符串对象("abc") 进行拼接,在代码的编译期间就已经完成,速度快
// 实际是等效的 String str5 = "abc" + "d" + "e" ; String str6 = "abcde" ;
3. String str = 变量 + 常量 ,则相当于 str = new String(新的str )
String str = "abc" ; str = str + "d" ; // 此处的str 不同于 上一个 str ,虽然名字相同
(1) 栈中 str ,指向 堆中 "abc"
(2) 堆中将 "abc" 拷贝一份 + "d" 后重新开辟一个空间
(3) 栈中 str , 指向 堆中 "abcd" 的空间
(4) 原 "abc" 等待 GC 回收
4.String 修饰的内容是不可改变的,一旦重新赋值,就会生成新的对象
String str1 = "a"; String str2 = str1 + "b" ; // str2 生成新的对象 String str3 = "ab" ; System.out.println(str2 == str3) ; // false
5.字符串拼接使用
String str = "a"; String str1 = "b" ; String str3 = str + str1 ; ==> StringBuilder str4 = new String(str);str4.append(str1);str4.toString();
单线程:StringBuider
多线程:StringBuffer
只生成一次对象,后续都是对已生成对象的拼接操作
场景:
在 for 循环中拼接字符串
多次将字符串重新拼接,str = str + "a" ;
五、值引用与对象引用
/** * @param args */ public static void main(String[] args) { String string = "a" ; change(string); System.out.println(string); // 输出 a } public static void change(String string){ string = "b" ; }
main 方法中 string 与 change 方法中 string ,虽然同名,但不是同一个对象,而是两个不同的对象
main() 中 string 指向了 堆中的 "a"
chang() 中 string 接收了 main 中 string 所指向的堆空间的地址
string = "b" ,相当于重新赋值,新生成了一个 字符串 空间,存放 b ,string 指向了新的空间
main() 中 string 指向的 堆空间的地址存放的内容未改变,输入依然为 a
String 方法的注释
/** * <p> * Strings are constant; their values cannot be changed after they * are created. String buffers support mutable strings. * Because String objects are immutable they can be shared. For example: * <p><blockquote><pre> * String str = "abc"; * </pre></blockquote><p> * is equivalent to: * <p><blockquote><pre> * char data[] = {‘a‘, ‘b‘, ‘c‘}; * String str = new String(data); * </pre></blockquote><p> */
String str = "abc" 等价于
char data[] = {‘a‘,‘b‘,‘c‘};
String str = new String(data) ;
六、intern()
String str1 = new String("abc"); String str2 = "abc"; System.out.println(str1.intern() == str2); // true
intern() 查找缓冲池中是否有与当前内容相匹配的字符串,如果有,则返回;如果没有则创建,再返回
即,intern() 是从缓冲池中返回,所以相同。
本文出自 “命运的左岸” 博客,请务必保留此出处http://mingyundezuoan.blog.51cto.com/4012317/1941775
String