Java进阶 创建和销毁对象
最近準(zhǔn)備寫點Javase的東西,希望可以幫助大家寫出更好的代碼。
1、給不可實例化的類提供私有構(gòu)造器
比如:每個項目中都有很多工具類,提供了很多static類型的方法供大家使用,誰也不希望看到下面的代碼:
TextUtils textUtils = new TextUtils();if(textUtils.isDigitsOnly("123")){//doSometing}else{//doSomething}自己寫個工具類,總有人喜歡先初始化個實例在調(diào)用方法,然后還附帶一個警告:The static method isDigitsOnly(CharSequence) from the type TextUtils should be accessed in a static way 。 你建議他使用類名.方法,人家還不樂意,我又沒出錯,干嘛要改,錯了你負(fù)責(zé)么。所以最好的方式,讓他沒辦法new實例。為工具類添加私有構(gòu)造器:
public class TextUtils {private TextUtils() { /* cannot be instantiated */ }這是android的TextUtils的源碼,這樣就可以了,讓他妹的初始化實例~,當(dāng)然你也可以在私有方法里面扔個異常。 public class TextUtils{private TextUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated");}}
對于異常的使用,一盡量使用Java提供的異常類,這樣可以使你的API比較易讀和易懂。
2、正確使用String,避免創(chuàng)建不必要的對象
很多人面試的時候都遇到過這樣的問題:String s = new String("abc");請問創(chuàng)建了幾個對象。也從側(cè)面說明了這是個反面的代碼寫法:
a、String s = new String("abc");“abc”本身就是一個String的實例,所以new String創(chuàng)建了不必要的String實例
b、如果改寫成 String s = "abc",不僅只創(chuàng)建了一個實例,而且在同一臺VM中,對于“abc”(字符串的字面常量)還會重用。
3、優(yōu)先使用基本類型,Java提供了8種基本類型,以及對應(yīng)的裝箱基本類型,且在Java1.5 提供了自動裝箱和解箱操作,雖然方便了代碼的編寫,但是如果不注意,可能帶來不好的效果。
看下面的代碼:
long start = System.nanoTime();Long sum = 0L;for (long i = 0; i < Integer.MAX_VALUE; i++){sum += i;}System.out.println(sum);System.out.println(System.nanoTime() - start);//20995956735如果你觀察了內(nèi)存,會發(fā)現(xiàn),一直GC一直在內(nèi)存回收,并且計算時間需要20多秒,如果我說這段代碼有個bug,導(dǎo)致代碼運行很慢,以及耗費內(nèi)存,你能找到嗎?
下面我修改下代碼:
long start = System.nanoTime();long sum = 0l;for (long i = 0; i < Integer.MAX_VALUE; i++){sum += i;}System.out.println(sum);System.out.println(System.nanoTime() - start);//5029758632這次運行不會出現(xiàn)GC一直回收內(nèi)存,且速度也只需要5秒左右,可能眼神不好的,沒有發(fā)現(xiàn)哪個地方修改了。
問題就出在自動裝箱、解箱上。第一次的程序sum為Long類型,在計算sum+=i;時會把sum自動解箱成long sum 然后運算,運算完成后,再裝箱成Long sum,導(dǎo)致程序構(gòu)造了大約2的32次方個多余Long實例。所以各位且用且嚴(yán)謹(jǐn)。
4、對于自己管理內(nèi)存的類,一定要清除不必要的對象引用,防止內(nèi)存泄漏
看下面的代碼:
package com.zhy._01;import java.util.Arrays;/** 使用數(shù)組模擬棧*/ public class MyStack {private static final int DEFAULT_INIT_SIZE = 10;private Object[] eles = new Object[DEFAULT_INIT_SIZE];/*** 當(dāng)前棧頂索引*/private int currentIndex;/*** 彈棧* * @return*/public Object pop(){if (currentIndex == 0)throw new ArrayIndexOutOfBoundsException("stack is empty");return eles[--currentIndex];}/*** 壓棧* * @param o*/public void push(Object o){ensureCapacity();eles[currentIndex++] = o;}private void ensureCapacity(){if (eles.length == currentIndex){eles = Arrays.copyOf(eles, currentIndex * 2 + 1);}}}代碼中存在一個地方,導(dǎo)致了內(nèi)存泄漏,你可以發(fā)現(xiàn)不? return eles[--currentIndex];
這行代碼導(dǎo)致,如果棧增長了特別大,然后調(diào)用多次pop彈棧,雖然currentIndex小了,但是棧始終保持中之前pop出的過期對象的引用,這就導(dǎo)致了內(nèi)存泄漏。如果不注意甚至最終造成OOM。
應(yīng)該改為:
/*** 彈棧* * @return*/public Object pop(){if (currentIndex == 0)throw new ArrayIndexOutOfBoundsException("stack is empty");Object tmp = eles[--currentIndex];eles[currentIndex] = null ; return tmp ; }當(dāng)然了,不要因為擔(dān)心內(nèi)存泄漏,在每個變量使用完成后都添加xxx=null,對于消除過期引用的最好方法,就是讓包含該引用的變量結(jié)束生命周期,而不是顯示的清空。一般情況下,對于類自己管理的內(nèi)存,應(yīng)當(dāng)警惕。
好了,就到這里,這些內(nèi)容都是我個人覺得值得知道,且在項目中會常遇到的,希望可以幫助到大家,嘿嘿,求評論,求贊。
轉(zhuǎn)載于:https://www.cnblogs.com/oversea201405/p/3752027.html
總結(jié)
以上是生活随笔為你收集整理的Java进阶 创建和销毁对象的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于Sql语句的心得体会
- 下一篇: 四则运算2任务完成表