java中new一個對象放在循環體里面與外面的區別


首先說下問題:

這次在做項目的是出現了一個new對象在循環里面與外面造成的不同影響。

大家可以看到這個new的對象放在不同的位置產生的效果是不一樣的。

經過多方查詢與驗證可以得出結論:

* EasyUITree tree=new EasyUITree();
*放外邊是同一塊內存空間,你的list中看似有了很多tree,其實都是同一個tree對象,tree的內容是你最后一次修改的內容,所以最終樹的的節點都是一樣的
而你放在里面的時候,每次都開辟了一個新的內存空間,也就是新的對象tree,所以list存的都是一個個獨立的tree對象,內容自然不一樣
*/

所以:在循環體外,始終都是這一個對象,循環放入的都是最新的值。

        在循環體內,創建的是不同的對象,每次放入的對應這不同值的對象。

下面是具體的jvm的一些解釋:

 

事實上在Java的GC機制中如果一個對象有着具體的引用,那么是不會被GC自動回收的。
也就是說:

Object obj = new Object();//寫在100個循環內等於你有100個引用對應了100個對象
所以100個對象在一段時間內都是會占用內存,直到內存不足GC主動回收

obj = new Object();//寫在100個循環內等於你使用1個引用分別100次調用了100個對象
所以當后一個對象init后,前一個對象已經是“無引用狀態”,會很快的被GC自動回收
(在你的循環還未結束時,可能已經進行了多次GC回收,這點很重要)

也就是說第二種方法能更好的管理內存。

p.s.
Java高性能編程就是通過程序員對代碼的掌控更切合計算機的識別與效率,
如果題主覺得安全更重要(但我沒想到會有什么安全問題)那也可以按照你的方法,
畢竟時代在進步,編程也沒必要按部就班,能實現功能、保證效率就好。

鏈接:https://www.zhihu.com/question/31751468/answer/88626975

 
用內存角度來解釋的話,在JVM的方法棧和堆內存這兩個內存中,當運行Object obj = new Object();時,在方法棧的棧頂中放入Object obj,然后在堆中生成一個Object對象,最后方法棧中的obj指向Object對象,這時完成一次循環的內存動作。接着第二次循環, new Object();又產生一個新的Object對象,然后方法棧中的obj指向新的Object對象,第一次循環的Object對象沒有被任務變量引用,成為了垃圾,等JVM垃圾回收器回收。其它循環以此類推了。
在這里我提一下題外話,JVM有個優秀的算法是,JVM的方法棧,一個方法的調用產生一個棧幀,這個棧幀在方法調用時計算出你有幾個局部變量,這個計算會過濾作用域的,如你的循環后面再建立一個局部變量,那JVM認為只有一個局部變量,因為你的Object obj = new Object();在大括號內,出了大括號就沒有了,所以只需要一個位置來存放局部變量即可,也就是說運行到大括號時用這個位置來執行代碼,出了大括號后下一個局部變量就可以接着使用這個棧的這個位置來執行下面的代碼了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM