1. 程式人生 > >Effective-Java(Item 41)之小心地使用過載

Effective-Java(Item 41)之小心地使用過載

先說一下過載與重寫的區別,很多人會把這兩個概念混淆:

1.過載是靜態的,發生在compile時期,由編譯時型別決定呼叫方法,通常出現在=號左邊的為編譯時型別,如Collection<?>[] collections = {};中編譯時型別為Collection;
重寫是動態的,發生在runtime時期,根據執行時物件呼叫對應方法;

2.過載發生在一個類中,要求方法名相同,引數列表不同;
重寫發生在祖先類和子孫類中,要求返回值、方法名、引數列表完全一致,子孫類throws的異常不得大於祖先類異常,子孫類訪問修飾符不得低於祖先類;

// Broken! - What does this program print?
public class CollectionClassifier {
    public static String classify(Set<?> s) {
        return "Set";
    }
    public static String classify(List<?> lst) {
        return "List";
    }
    public static String classify(Collection<?> c) {
        return "Unknown Collection";
    }
    public static void main(String[] args) {
        Collection<?>[] collections = {
            new HashSet<String>(),
            new ArrayList<BigInteger>(),
            new HashMap<String, String>().values()
        };
        for (Collection<?> c : collections)
            System.out.println(classify(c));
    }
}

輸出居然是3次Unknown Collection,因為collections的每個元素的編譯時型別是Collection<?>,過載時呼叫都是classify(Collection<?> c);方法;

過載可以先考慮下面這些情況:

使用instanceof來判斷物件型別替代過載
public static String classify(Collection<?> c) {
    return c instanceof Set ? "Set" :
           c instanceof List ? "List" : "Unknown Collection";
}   
給方法不同的名字替代過載
// java.io.ObjectOutputStream
使用writeBoolean(boolean),writeInt(int)和writeLong(long)方法而不是過載write方法