談談java創建對象
阿新 • • 發佈:2017-05-19
裏的 最大 線程安全 tostring 現實 創建多個對象 語言 安全問題 thread
作為一門面向對象的語言,我們學習java,對於對象的學習非常重要。大多的教程上都用抽象的概念驅使著我們理解對象,把現實抽象為對象。然而忽略對創建對象的研究。如果說學習抽象思維,運用抽象思維虛擬現實是走向java頂端的關鍵,那創建對象可以說是通向成功的墊腳石吧。今天我們就來談談創建對象。
說到創建對象,new 方法是java最常用也是最簡單的方式。而恰恰是它的簡單,讓我們用的那麽的隨意。
舉個例子:
public class Demo { private String i; private String love; private String java; public String getDemo(){ return i + love + java; } }
編譯器如果不為我們優化,調用一次getDemo我們將創建2個對象。而我們都清楚,可以使用stringbuffer和stringbuilder代替。
public class Demo { private String i; private String love; private String java; public String getDemo(){ StringBuilder builder = new StringBuilder(); builder.append(i); builder.append(love); builder.append(java); return builder.toString(); } }
這樣是解決了調用一次getDemo創建多個對象,但是調用多次getDemo呢??
public class Demo { private String i; private String love; private String java; private final ThreadLocal<StringBuilder> cache = new ThreadLocal<StringBuilder>(); public String getDemo(){ StringBuilder builder = cache.get(); if(builder==null){ builder = new StringBuilder(); cache.set(builder); }else{ builder.delete(0, builder.length()); } builder.append(i); builder.append(love); builder.append(java); return builder.toString(); } }
public class Demo { private String i; private String love; private String java; private final ThreadLocal<StringBuilder> cache = new ThreadLocal<StringBuilder>(); public String getDemo(){ StringBuilder builder = cache.get(); if(builder==null){ synchronized (this) { builder = new StringBuilder(); cache.set(builder); } }else{ builder.delete(0, builder.length()); } builder.append(i); builder.append(love); builder.append(java); return builder.toString(); } }
我們使用了成員屬性來解決多次調用getDemo創建多個stringbuilder類型的變量。熟悉多線程的你應該已經考慮安全的問題了。是的,使用成員屬性容易引起線程安全問題。上面代碼裏的判斷非空和set是非安全的。我們做修改後如下:
我們編寫的程序,方法中每個new操作,運行在多線程情況下,最終會產生n個對象。我們知道new 創建的對象存在於堆中,它不會隨著線程的執行結束而釋放。而對於這些對象的回收,我們需要jvm的垃圾回收來完成,而垃圾回收什麽時候開始,回收效果如果,我們往往不會去關註。
可以確定的是,我們都希望著jvm立刻回收不需要使用的對象,以便我們可以最大限度的使用內存。但是我們為什麽不從源頭,從創建的時刻,盡量少的使用它呢。
以上是我個人的理解,如有錯誤,敬請糾正。
談談java創建對象