String.java

1.为什么String是final class?

目前结论:首先,final是为了不能让类继承。而不能继承是为了维护String是一个constant,具有immutable的性质。一旦创建,它就不可以被修改。具体见4

2.实验证明String是一个constant

理解重点:将变量a,p和String本身,如"apple"看成三个不同的东西。a,p是在stack上的引用/变量。"apple"根据初始化的不同在heap或者constant pool中

  • 实验1,注意对比指针(变量)a和p的关系
String a = "apple";
String p = a;
System.out.println(a == p); // true
p = "pear";
System.out.println(a == p); // false

  • 实验2,注意观察指针a地址的改变
String a = "apple"; // byte[5]@946
String p = a; // byte[5]@946
System.out.println(a == p); // true
a += "red "; // byte[9]@961
System.out.println(a == p); // false
  • 实验3,注意观察String a和StringBuffer p内容的改变
public static void main(String[] args) {
    String a = "apple"; // byte[5]@946
    append(a);
    System.out.println(a); // apple

    StringBuffer p = new StringBuffer("apple");
    appendBuffer(p);
    System.out.println(p); // green apple
}

public static String append(String s) {
    return "red " + s;
}

public static void appendBuffer(StringBuffer p) {
    p.insert(0, "green ");
}

因为String immutable的性质,在进行+操作时会新创建一个对象,在loop中使用string会特别慢。所以一般使用StringBuilder或者StringBuffer。

todo : String的回收

3.String不同的初始化方式

  • 在Heap中初始化,ab指向地址不同
String a = new String("object");
String b = new String("object");
System.out.println(a == b);// stored in heap, return false
System.out.println(a.intern() == b.intern());// stored in constant pool, return true
  • 在constant pool(method area)中初始化,ab指向一个字符串
String a = "constant";
String b = "constant";
System.out.println(a == b);// stored in constant pool, return true
System.out.println(a.intern() == b.intern());// exactly return true

4.如果String可以被继承

这是一个新创建一个不带finalMyString类,然后使用FuckMyString子类继承,最后改变MyString值的故事

class MyString {

    private final byte[] values;

    public MyString(byte[] bytes) {
        values = bytes;
    }

    public byte[] toArray() {
        return this.values;
    }

    public void getContent() {
        for (byte b : values) {
            System.out.print(b);
        }
    }
}

public class FuckMyString extends MyString {

    private final byte[] someValues;

    public FuckMyString(byte[] bytes) {
        super(bytes);
        someValues = bytes;
    }

    public static void main(String[] args) {
        FuckMyString dummy = new FuckMyString(new byte[]{'a', 'b', 'c'});
        MyString string = dummy;
        dummy.getContent(); // 979899
        // change the byte array that both pointer "values" and "someValues" pointed to
        dummy.someValues[0] = 'b';
        dummy.getContent(); // 989899
        System.out.println();
        // Finally we change the value in MyString
        string.getContent(); // 989899
    }
}

根本原因是因为private final byte[] values;中的final仅仅是保持values地址不变,而不能保证其中的值不变。

todo(important) encode/decode

COMPACT_STRINGS, coders, bytes[]等还在路上

results matching ""

    No results matching ""