記錄一下今天被蠢到
1. 在觀察StringBuffer類的toString方法時,發現了個沒見過的方法
return new String(toStringCache, true);
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
2. 發現它傳了一個true進去,然后點進去后
發現它對傳進去的true沒有做任何操作,學到了一種新的“方法重載思想”,傳一個boolean只是為了區分方法
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}
在此處我發現這個this.value = value;
此時就很懵,這個是String類里面的value,這個不是不可以修改的么,然后各種查,各種測試
private final char value[];
最后發現這個是一個new String 操作,所以對一個final修飾的value[]來說,此時他還沒有被賦值,所以是可以進行第一次賦值的
3. 那么話又說回來了,這個方法和不傳boolean的有什么區別呢?
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}
我們可以觀察到方法的修飾符不同,一個是public的,一個是默認的,也就是只有同包才能訪問,StringBuffer與String都是屬於java.lang包下的,所以StringBuffer可以使用,而我們是使用不了的,因為如果交給我們使用的話,可能會違反String是不可修改的原則的。
- 例如如下代碼:不能運行,只是示范
此時傳入的b是引用,s的value中保存的也是b的引用,所以可以認為此時的b與String中的value是同一個對象,此時修改b[1]的值的時候,String中final修飾的value就被修改了,很明顯不符合String的定義。
char [] b = {'b','c','1'};
String s = new String(b, true);
b[1] = 'a';
而直接傳入char[]數組的,是調用數組拷貝,將傳入的值一一賦值到String內置的value數組中,他們兩個是不同的兩個對象,也就保證了String類的不可修改
4. 最后我們來強行調用一下,利用反射
private static void test07() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
char[] a = {'1','f','l'};
Class<String> clazz = String.class;
Constructor<String> constructor = clazz.getDeclaredConstructor(char[].class, boolean.class);
constructor.setAccessible(true);
String s = constructor.newInstance(a, true);
System.out.println(s);
//此時修改a[1]的值
a[1]='c';
System.out.println(s);
}
我們觀察打印輸出,可以發現,String對象被我們修改了,也驗證了我們前面的說法
1fl
1cl
