日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一文弄懂String的所有小秘密

發布時間:2024/2/28 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文弄懂String的所有小秘密 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 簡介
  • String是不可變的
  • 傳值還是傳引用
  • substring() 導致的內存泄露
  • 總結

一文弄懂String的所有小秘密

簡介

String是java中非常常用的一個對象類型。可以說java中使用最多的就是String了。那么String到底有哪些秘密呢?接下來本文將會一一講解。

String是不可變的

String是不可變的,官方的說法叫做immutable或者constant。

String的底層其實是一個Char的數組。

private final char value[];

所有的String字面量比如"abc"都是String的實現。

考慮下面的賦值操作:

String a="abc"; String b="abc";

對于java虛擬機來說,"abc"是字符串字面量,在JDK 7之后,這個字符串字面量是存儲在java heap中的。而在JDK 7之前是有個專門的方法區來存儲的。

有了“abc”,然后我們將“abc” 賦值給a和b。

可以看到這里a和b只是java heap中字符串的引用。

再看看下面的代碼發生了什么:

String c= new String("abc");

首先在java heap中創建了“abc”,然后調用String的構造函數:

public String(String original) {this.value = original.value;this.hash = original.hash;}

在構造函數中,String將底層的字符串數組賦值給value。

因為Array的賦值只是引用的賦值,所以上述new操作并不會產生新的字符串字面值。

但是new操作新創建了一個String對象,并將其賦值給了c。

String的不可變性還在于,String的所有操作都會產生新的字符串字面量。原來的字符串是永遠不會變化的。

字符串不變的好處就在于,它是線程安全的。任何線程都可以很安全的讀取字符串。

傳值還是傳引用

一直以來,java開發者都有這樣的問題,java到底是傳值還是傳引用呢?

我想,這個問題可以從兩方面來考慮。

首先對于基礎類型int,long,double來說,對他們的賦值是值的拷貝。而對于對象來說,賦值操作是引用。

另一方面,在方法調用的參數中,全部都是傳值操作。

public static void main(String[] args) {String x = new String("ab");change(x);System.out.println(x); }public static void change(String x) {x = "cd"; }

我們看上面的例子,上面的例子輸出ab。因為x是對“ab”的引用,但是在change方法中,因為是傳值調用,所以會創建一個新的x,其值是“ab”的引用地址。當x被重新賦值之后,改變的只是拷貝之后的x值。而本身的x值是不變的。

substring() 導致的內存泄露

第一次看到這個話題,大家可能會很驚訝,substring方法居然會導致內存泄露?這個話題要從JDK 6開始講起。

我們先看下JDK 6的實現:

String(int offset, int count, char value[]) {this.value = value;this.offset = offset;this.count = count; }public String substring(int beginIndex, int endIndex) {//check boundaryreturn new String(offset + beginIndex, endIndex - beginIndex, value); }

可以看到,JDK 6的substring方法底層還是引用的原始的字符串數組。唯一的區別就是offset和count不同。

我們考慮一下下面的應用:

String string = "abcdef"; String subString = string.substring(1, 3); string = null;

雖然最后我們將String賦值為null,但是subString仍然引用了最初的string。將不會被垃圾回收。

在JDK 7之后,String的實現發送了變化:

public String(char value[], int offset, int count) {//check boundarythis.value = Arrays.copyOfRange(value, offset, offset + count); }public String substring(int beginIndex, int endIndex) {//check boundaryint subLen = endIndex - beginIndex;return new String(value, beginIndex, subLen); }

Arrays.copyOfRange將會拷貝一份新的數組,而不是使用之前的數組。從而不會發生上面的內存泄露的問題。

總結

雖然String是我們經常使用的對象,但是里面的原理還是值得我們了解的。

更多精彩內容且看:

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/string-all-in-one/

本文來源:flydean的博客

歡迎關注我的公眾號:程序那些事,更多精彩等著您!

總結

以上是生活随笔為你收集整理的一文弄懂String的所有小秘密的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。