国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Effective Java

2019-11-14 22:54:49
字體:
供稿:網(wǎng)友
Effective java - 方法的參數(shù)聲明

給方法的參數(shù)加上限制是很常見的,比如參數(shù)代表索引時不能為負(fù)數(shù)、對于某個關(guān)鍵對象引用不能為null,否則會進(jìn)行一些處理,比如拋出相應(yīng)的異常信息。

對于這些參數(shù)限制,方法的提供者必須在文檔中注明,并且在方法開頭時檢查參數(shù),并在失敗時提供明確的信息,即:

detect errors as soon as possible after they occur

這將成為準(zhǔn)確定位錯誤的一大保障。

如果沒有做到這一點,最好的情況是方法在處理過程中失敗并拋出了莫名其妙的異常,錯誤的源頭變得難以定位,但這是最好的情況。更差的情況是方法執(zhí)行通過,沒有發(fā)生任何錯誤,只是得出的結(jié)果和方法描述完全不符,最后在某個關(guān)鍵的部分看到奇怪的數(shù)據(jù)時才亡羊補牢。

對于參數(shù)違反有效性時使用的異常類,我們通常拋出IllegalArgumentException,IndexOutOfBoundsException,NullPointerException。而對于違反約束時拋出的異常類型,需要用Javadoc的@throws標(biāo)簽對其進(jìn)行說明。另外,并不是所有參數(shù)檢查都需要做到這種地步。如果方法或構(gòu)造器不對外導(dǎo)出,則可以簡單使用assert來保證參數(shù)的有效性。比如java.util.Collections$CopiesList:

PRivate static class CopiesList<E>        extends AbstractList<E>        implements Randomaccess, Serializable{        //...        CopiesList(int n, E e) {            assert n >= 0;            this.n = n;            element = e;        }        //...}

但是,有效性檢查并不都是簡單的,這一操作的代價也可能非常大甚至不切實際,于是有些操作直接將參數(shù)檢查隱含在計算過程中。比如java.util.Collectionssort()方法,列表中的元素當(dāng)然是都可比較的,而方法并沒有在開頭檢查有效性,而是計算中遇到問題時拋出異常。與這種方式相比,提前檢查有效性的意義確實不大。但在計算途中檢查參數(shù)的有效性需要考慮一點,即方法的原子性。

說道參數(shù)就不得不說方法重載,首先上一段例子:

import java.math.BigInteger;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Set;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));    }}

很常見的筆試題,會輸出三次"Unknown Collection",編譯時已決定了將調(diào)用的方法。與重載方法的靜態(tài)選擇(為什么當(dāng)初會這樣設(shè)計重載? overriding is the norm and overloading is the exception,似乎沒有人希望這種做法 )相對的是覆蓋方法,overridden method的選擇是動態(tài)的。

即,選擇方法是在運行時進(jìn)行的,子類用同樣的方法簽名覆蓋了上級類的方法,如果這個方法是實例方法則會在子類的實例上被調(diào)用。比如下面這個例子,實例的編譯時類型對其沒有造成影響:

class Wine {    String name() {        return "wine";    }}class SparklingWine extends Wine {    @Override    String name() {        return "sparkling wine";    }}class Champagne extends SparklingWine {    @Override    String name() {        return "champagne";    }}public class Overriding {    public static void main(String[] args) {        Wine[] wines = { new Wine(), new SparklingWine(), new Champagne() };        for (Wine wine : wines)            System.out.println(wine.name());    }}

鑒于重載方法的這種特征,而語言本身對其也沒有特別的限制,作者建議<不要提供相同參數(shù)數(shù)量的重載方法>,而對于可變參數(shù)則不要考慮重載。關(guān)于這個建議的不錯的例子就是ObjectOutputStream,對于其write方法,設(shè)計者并沒有提供相同參數(shù)數(shù)量的重載,而是提供了諸如writeInt,writeBoolean,writeLong等方法,而且read方法也是與write對稱的。這種方式不適用于構(gòu)造器,我們無法對構(gòu)造器進(jìn)行命名,但我們可以對構(gòu)造器進(jìn)行私有化并導(dǎo)出靜態(tài)工廠。但也并不能說必須嚴(yán)格遵守這種規(guī)則,比如為fetchSalaryInfo()提供了兩種方法重載,分別是int uid和User userInfo,很難想象會出現(xiàn)調(diào)用錯誤的情況。

破壞<不要提供相同參數(shù)數(shù)量的重載方法>這一規(guī)則不僅僅是出現(xiàn)在導(dǎo)出某個方法的時候,更新現(xiàn)有類的時候也有可能。比如String類有一個since 1.4的contentEquals(StringBuffer),另外還有一個since 1.5的contentEquals(CharSequence)。(Java 1.5版本中增加了CharSequence接口,并作為StringBuffer,StringBuilder,CharBuffer,String等類的公共接口)但這并不會帶來危害,因為這個例子的兩個重載方法的行為是完全一樣的。

對于泛型還有下面這種有趣的情況:

import java.util.ArrayList;import java.util.List;import java.util.Set;import java.util.TreeSet;public class SetList {    public static void main(String[] args) {        Set<Integer> set = new TreeSet<Integer>();        List<Integer> list = new ArrayList<Integer>();        for (int i = -3; i < 3; i++) {            set.add(i);            list.add(i);        }        for (int i = 0; i < 3; i++) {            set.remove(i);            list.remove(i);        }        System.out.println(set + " " + list);    }}

槽點:remove里的參數(shù)是index還是element?執(zhí)行結(jié)果是[-3,-2,-1][-2,0,2],也就是說 list.remove中的參數(shù)是index,而不是被自動裝箱。應(yīng)該說問題根本原因是List同時提供了remove(int)remove(E)嗎?但作為API的使用者,我們能做的僅僅是對Java 5的這一大特性持更謹(jǐn)慎的態(tài)度。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 洛宁县| 额济纳旗| 莎车县| 峡江县| 普格县| 彰武县| 甘洛县| 全椒县| 高州市| 衡南县| 渭源县| 新平| 清水河县| 杭锦旗| 逊克县| 肃南| 武夷山市| 延寿县| 谢通门县| 南阳市| 开鲁县| 景德镇市| 龙胜| 枞阳县| 丹江口市| 宝鸡市| 尼玛县| 昌江| 若尔盖县| 阿图什市| 长宁县| 宜章县| 左贡县| 博野县| 长子县| 噶尔县| 阳城县| 阳高县| 玛纳斯县| 东台市| 武城县|