首页 > 代码库 > String

String

String

一、构造方式

  1. 两种构造方式

        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[];


四、字符串拼接


  1.     String str = 字符串常量 或 匿名的字符串对象("abc") 进行拼接,在代码的编译期间就已经完成,速度快

  2.         // 实际是等效的
            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