“參考這位大神的”
滿足所有的條件時,substring調用了一個構造器,在這個構造器里直接拷貝數組,賦值給自己的私有變量 (外部無法訪問),從而創建一個新的字符串(String創建字符串,是使用char[ ]) 。 “修改后的substring的效率變低了,并且占用了更多的內存,無論是從時間上還是空間上都比不上原有的實現”
//JDK1.7之前的substringpublic String substring(int beginIndex) { //省略判斷,按理想條件走 return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex, endIndex - beginIndex,value);}// Package PRivate constructor which shares value array for speed.String(int offset, int count, char value[]) { this.value = value; this.offset = offset; this.count = count;}//通過復用數組value,省去了數組拷貝的開銷,僅通過3個賦值語句就創建了一個新的字符串對象改變前: 性能好,效率高 改變后: “掩蓋了優點”
那為什么要修改substring呢?為什么要犧牲其性能呢?
因為安全嗎?復用數組有安全隱患嗎?
舊版JDK:創建一個String對象,通過復制參數內部的數組(this.value=value)實現 。但不會有安全問題:比方說一個字符數組arr,原來是{‘h’,’e’,’l’,’l’,’o’},作為參數傳給了String的構造方法,創建了一個String對象;當改變arr的內容時,創建的那個String對象沒有變化(因為復制是使用的String私有的char[ ],外部無法訪問)。
arr=new arr[]{'h','e','l','l','o'};str = new String(0, arr.length, arr) // 順序和新版的不一樣System.out.print(str); // helloarr[0]='A';System.out.print(str); // hello 木有改變新版JDK:創建一個String對象,通過Arrays.copyOf方法實現 。更不會有安全問題了,來一個參數就創建一個新的String對象,即使兩個參數一模一樣,創建出來的對象也不相等(==)。
木有安全問題,那為什么要改變呢? 我查了一下2011年互聯網發生了啥事,好多 。
因為舊版的可能存在內存泄漏的問題 。 從網絡上抓個東西(A),假設100個字節長度,將A變為String對象(B),只截取其中的10個字節長度(C) 。問題來了,假設GC把A清理走了,但B還保留著A的100個字節長度的東西,導致內存泄漏 (和內存溢出的區別,參看別人的總結不讓轉載的,鏈接過去不知有沒有問題啊?) 。 新版的可以把字符串對象和內部數組一起回收,更加健壯??!
總結
舊版的substring性能好,但在某些情況下內存泄漏是個很嚴重的問題;新版的substring更加健壯,卻犧牲了性能 。孰優孰劣,無從評判~~
新聞熱點
疑難解答