更新時間:2020-03-13 10:08:28 來源:動力節點 瀏覽4432次
有時候奇怪的發現往list添加數據的時候,一直被最后一個元素覆蓋,首先,我們得明白原理:
在new一個對象的時候,對象的ID是唯一確定的;將對象add入list中時,放入list中的其實是對象的引用;而每次循環只是簡單的set對象的屬性,set新的屬性值,而add進list中的對象還是同一個對象id,也就是同一個對象;
所以每次add之后,list發現對象引用和之前元素一樣,就覆蓋掉了之前add的對象。所以循環之后list中的對象是重復的對象。
想要避免這個問題只要每次add時保證對象引用都是不同的即可,即每循環一次重新new一個對象。
new的對象應該放在for循環內,每循環一次重新new一個新對象
它的確是在main方法棧中先后創建了10個引用叫obj,然后每個obj指向不同的new出來的對象。
關鍵是:每次循環體執行完后,循環體內定義的代碼塊局部變量、對象如果沒有被繼續引用,就立即被銷毀了;即obj變量、new出來的對象都被銷毀了。
一般是循環一次一個新對象,所以如非必要,不要在循環里面創建對象。
用內存角度來解釋的話,在JVM的方法棧和堆內存這兩個內存中,當運行Objectobj=newObject();時,在方法棧的棧頂中放入Objectobj,然后在堆中生成一個Object對象,最后方法棧中的obj指向Object對象,這時完成一次循環的內存動作。接著第二次循環,newObject();又產生一個新的Object對象,然后方法棧中的obj指向新的Object對象,第一次循環的Object對象沒有被任務變量引用,成為了垃圾,等JVM垃圾回收器回收。其它循環以此類推了。
在這里我提一下題外話,JVM有個優秀的算法是,JVM的方法棧,一個方法的調用產生一個棧幀,這個棧幀在方法調用時計算出你有幾個局部變量,這個計算會過濾作用域的,如你的循環后面再建立一個局部變量,那JVM認為只有一個局部變量,因為你的Objectobj=newObject();在大括號內,出了大括號就沒有了,所以只需要一個位置來存放局部變量即可,也就是說運行到大括號時用這個位置來執行代碼,出了大括號后下一個局部變量就可以接著使用這個棧的這個位置來執行下面的代碼了
再看一個例子:
結果:
解釋:
在for循環內部創建的話,每次執行循環都會創建對象,沒什么特別明顯壞處,只是會消耗內存。所以我們通常在for循環外部實例化對象,因為它執行一次
Objectobj是創建對象引用,引用的實例地址。newObject();是創建對象實例
兩者都會占用系統資源。
改進之前for循環中創建了10次引用和10實例,改進后是創建了1次引用,10實例。
在方法執行完后內存資源會被回收
以上就是動力節點Java培訓機構小編介紹的“Javase高級教程:for循環創建對象”的內容,希望對大家有幫助,如有疑問,請在線咨詢,有專業老師隨時為你服務。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習