Effective Java 案例分享(二)

7、拋棄廢棄的對(duì)象引用

當(dāng)一個(gè)對(duì)象不再使用時(shí),應(yīng)該將該引用設(shè)置為null,避免該對(duì)象并不能被JVM回收。文中列出以下幾種情況:

  • 數(shù)組中的對(duì)象,使用結(jié)束后要把對(duì)應(yīng)的未知的引用設(shè)置為null;
  • 注意緩存對(duì)象的存活時(shí)間;
  • 注意listener和callback的添加和移除;

8、避免使用FINALIZERS和CLEANERS

Java為對(duì)象提供了finalize方法,當(dāng)對(duì)象被準(zhǔn)備回收時(shí)調(diào)用,在Java 9之后廢棄finalize,使用Cleaner,但是兩者都是不推薦使用的。 Java提供了便捷的內(nèi)存回收算法,如果重寫(xiě)了finalize,可能導(dǎo)致GC無(wú)法回收足夠的內(nèi)存空間,增加OutOfMemoryError的幾率,也增加了GC的工作時(shí)長(zhǎng),所以我們不應(yīng)該在finalize或者cleaner中嘗試修改對(duì)象的持久化狀態(tài)。為了防止finalize被惡意攻擊,可以把finalize方法設(shè)置為final。

finalize的常用場(chǎng)景:

public class FileOutputStream extends OutputStream{

    protected void finalize() throws IOException {
        // Android-added: CloseGuard support.
        if (guard != null) {
            guard.warnIfOpen();
        }

        if (fd != null) {
            if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
                flush();
            } else {
                // Android-removed: Obsoleted comment about shared FileDescriptor handling.
                close();
            }
        }
    }

{

應(yīng)該以finalize為時(shí)間點(diǎn),為對(duì)象的回收做準(zhǔn)備,以上面的FileOutputStream為例,在finalize執(zhí)行時(shí),清除緩沖區(qū)或關(guān)閉文件流,保證對(duì)象在回收時(shí)不會(huì)產(chǎn)生內(nèi)存問(wèn)題。如果你希望你的對(duì)象具有自動(dòng)回收功能,可以實(shí)現(xiàn)AutoCloseable接口,并在finalize中調(diào)用實(shí)現(xiàn)close方法。

9、使用try with resource 替換 try-finally

請(qǐng)注意,此語(yǔ)法Java 7以下不支持。

我們經(jīng)常使用FileInputStream或FileOutStream等資源型的類(lèi),需要在使用結(jié)束后,及時(shí)關(guān)閉資源。在過(guò)去,使用try-finally是最好的方式:

static String firstLineOfFile(String path) throws IOException {
    BufferedReader br = new BufferedReader(newFileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}

如果一次操作使用多次資源型的類(lèi),例如以下代碼:

static void copy(String src, String dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            byte[] buf = new byte[BUFFER_SIZE];
            int n;
            while ((n = in.read(buf)) >= 0)
                out.write(buf, 0, n);
        } finally {
            out.close();
        }
    } finally {
            in.close();
    }
}

以上代碼存在以下缺點(diǎn):

  • 因?yàn)橐P(guān)閉資源,導(dǎo)致上面的代碼需要有多個(gè)try-finally,可讀性上并不好
  • close方法本身也會(huì)拋出異常
  • 兩個(gè)資源型的操作互相影響

如果資源性的操作再?gòu)?fù)雜一些,代碼會(huì)更加復(fù)雜,為了解決這個(gè)問(wèn)題,在Java 7之后提供了新的語(yǔ)法:

static String firstLineOfFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

static void copy(String src, String dst) throws IOException {
    try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new byte[BUFFER_SIZE];
        int n;
        while ((n = in.read(buf)) >= 0)
        out.write(buf, 0, n);
    }
}

此語(yǔ)法要求try方法內(nèi)的資源必須實(shí)現(xiàn)AutoCloseable接口,如果發(fā)生了異常,會(huì)自動(dòng)調(diào)用該類(lèi)的close方法。同樣支持try-catch捕獲指定的異常。

static String firstLineOfFile(String path, String defaultVal) {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    } catch (IOException e) {
        return defaultVal;
    }
}

10、遵循重寫(xiě)Object的equals方法的規(guī)則

重寫(xiě)Object的equals方法雖然很簡(jiǎn)單,但是有很多種方式出錯(cuò),并且后果很?chē)?yán)重。一般來(lái)說(shuō)我們不必重寫(xiě)equals方法,因?yàn)槊恳粋€(gè)Object的equals已經(jīng)保證了它的唯一性,如果必須要重寫(xiě)他,要注意以下原則:

  • 自反性:x.equals(x),必須返回true;
  • 對(duì)稱性:x.equals(y) == y.equals(x);
  • 傳遞性:如果x.equals(y) ==true,y.equals(z) == true, 所以x.equals(z) == true;
  • 一致性:x.equals(y)的結(jié)果,如果未發(fā)生改變,無(wú)論調(diào)用多少次都會(huì)得到同一個(gè)結(jié)果;
  • 非空性:x非空,x.equals(null)必須返回false;

其他判斷相等的方法:

  • 數(shù)字的比較,如果不是float和double,可以直接使用==判斷相等,如果是float,使用Float.compare(float, float),如果是Double,使用Double.compare(double, double);
  • 如果需要判斷數(shù)組的每一個(gè)元素相等,可以考慮使用Arrays.equals()方法;
  • 避免判斷空指針,可以使用Objects.equals()方法;

如果需要重寫(xiě)equals,也一定還要重寫(xiě)hashcode,并且遵循equals的方法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容