第一章 Java開發(fā)中通用的方法和準(zhǔn)則

不要在常量和變量中出現(xiàn)易混淆的字母

包名全小寫,類名首字母全大寫佩谷,常量全部大寫并用下劃線分割辞做,變量采用駝峰(Camel Case)命名。在變量的聲明中不要引入容易混淆的字母:

long i=1l;
System.out.println("i的兩倍是:"+(i+i));

如果字母和數(shù)字混合使用,字母“l(fā)”務(wù)必大寫框喳,字母“O”則增加注釋五垮。
注意杜秸,字母“l(fā)”作為長整型標(biāo)志時(shí)務(wù)必大寫撬碟。

莫讓常量蛻變成變量

加了final和static的常量可能會(huì)變嗎莉撇?

interface ConstDemo {
    public static final int RAND_CONST = new Random().nextInt();
}
System.out.println("常量會(huì)變哦:" + ConstDemo.RAND_CONST);

常量就是常量棍郎,在編譯器就必須確定其值银室,不應(yīng)該在運(yùn)行期更改,負(fù)責(zé)程序的可讀性會(huì)非常差蜈敢,甚至連作者自己都不能確定在運(yùn)行 期發(fā)生了何種神奇的事情辜荠。

三元操作符的類型務(wù)必一致

 int i = 80;
String s = String.valueOf(i < 100 ? 90 : 100);
String s1 = String.valueOf(i < 100 ? 90 : 100.0);
System.out.println("兩者是否相等:" + s.equals(s1));

三元操作符類型的轉(zhuǎn)換規(guī)則:
若兩個(gè)操作數(shù)不可轉(zhuǎn)換,則不做鉆換抓狭,返回值為Object類型
若干兩個(gè)操作數(shù)是明確類型額表達(dá)式(比如變量)侨拦,則按正常的二進(jìn)制數(shù)字來轉(zhuǎn)換,int類型轉(zhuǎn)換為long類型辐宾,long類型轉(zhuǎn)換為float類型等狱从。
若兩個(gè)操作數(shù)中有一個(gè)是數(shù)字S,另外一個(gè)是表達(dá)式,且其類型標(biāo)識(shí)為T,那么叠纹,若數(shù)字S在T的范圍內(nèi),則轉(zhuǎn)換為T類型誉察;若S超出T類型的范圍与涡,則T轉(zhuǎn)換為S類型
若兩個(gè)操作數(shù)都是直接量數(shù)字,則返回值類型為范圍較大者持偏。

注意保證三元操作符中兩個(gè)操作數(shù)類型一致驼卖,即可減少錯(cuò)誤的發(fā)生。

避免帶有變長參數(shù)的方法重載

 public void calPrice(int price, int discount) {
        float knockdownPrice = price * discount / 100.0F;
        System.out.println("簡單折扣后的價(jià)格是:" + formateCurrency(knockdownPrice));
    }

    public void calPrice(int price, int... discounts) {
        float knockdownPrice = price;
        for (int discount : discounts) {
            knockdownPrice = knockdownPrice * discount / 100;
        }
        System.out.println("復(fù)雜折扣后的價(jià)格是:" + formateCurrency(knockdownPrice));
    }

    private String formateCurrency(float price) {
        return NumberFormat.getCurrencyInstance().format(price / 100);
    }

Java在編譯時(shí)鸿秆,首先會(huì)根據(jù)實(shí)參的數(shù)量和類型來進(jìn)行處理酌畜,也就是查到calPrice(int price,int discount)方法,而且確認(rèn)它是否符合方法簽名條件卿叽。
int是一個(gè)原生數(shù)據(jù)類型桥胞,而數(shù)組本身是一個(gè)對象,編譯器想要“偷懶”考婴,所以會(huì)這樣選擇贩虾。

慎用變長參數(shù)的方法重載,讓人傷腦經(jīng)不說沥阱,蘇紅補(bǔ)丁哪天就陷入這類小陷阱里了缎罢。

別讓null值和空值威脅到變長方法

public class Client {
    public void methodA(String str, Integer... is) {
    }

    public void methodA(String str, String... strs) {
    }

    public static void main(String[] args) {
        Client client = new Client();
        client.methodA("China", 0);
        client.methodA("China", "People");
        client.methodA("China", null);
    }
}
public static void main(String[] args){
    Client client = new Client();
    String[] strs = null;
    client.methodA("China",strs);
}

讓編譯器知道這個(gè)null值是String類型的,編譯即可順利通過,也就減少了錯(cuò)誤的發(fā)生策精。

覆寫變長方法也循規(guī)蹈矩

在Java中舰始,子類覆寫符類的方法很常見,這樣做既可以修正Bug也可以提供擴(kuò)展的業(yè)務(wù)功能支持蛮寂,同時(shí)還符合開閉原則(Open-Closed Principle)蔽午。覆寫必須滿足的條件:
重寫方法不能縮小訪問權(quán)限。
參數(shù)列表必須與被重寫方法相同酬蹋。
返回類型必須與重寫方法的相同或者是其子類及老。
重寫方法不能拋出新的異常,或者超出符類范圍的異常范抓,但是可以拋出更少骄恶,更有限的異常,或者不拋出異常匕垫。

public class Client {
    public static void main(String[] args) {
        Base base = new Sub();
        base.fun(100, 50);
        Sub sub = new Sub();
        sub.fun(100, 50);
    }
}

class Base {
    void fun(int price, int... discounts) {
        System.out.println("Base.....fun");
    }
}

class Sub extends Base {
    @Override
    void fun(int price, int[] discounts) {
        System.out.println("Sub.....fun");
    }
}

警惕自增的陷阱

int count = 0;
            for (int i = 0; i < 10; i++) {
                count = count++;
            }
            System.out.println("count=" + count);

結(jié)果是0

count++是一個(gè)表達(dá)式僧鲁,是由返回值的,它的返回值就是count自加前的值象泵,Java對自加是這樣處理的:首先把count的值(注意是值寞秃,不是引用)拷貝到一個(gè)臨時(shí)變量區(qū),然后對count變量加1偶惠,最后返回臨時(shí)變量區(qū)的值春寿。程序第一次玄幻時(shí)的詳細(xì)處理步驟如下:
1.JVM把count的值(其值是0)拷貝到臨時(shí)變量區(qū)
2.count值加1,這時(shí)候count的值是1
3.返回臨時(shí)變量區(qū)的值忽孽,注意這個(gè)值是0绑改,沒修改過。
4.返回值賦值給count兄一,此時(shí)count值被重置成0.

不要讓舊語法困擾你

Java中沒有了goto關(guān)鍵字厘线,但是擴(kuò)展了break和continue關(guān)鍵字。

少用靜態(tài)導(dǎo)入

靜態(tài)導(dǎo)入語法(import static)其目的是為了減少字符串輸入量出革,提高代碼的可閱讀性造壮,以便更好的理解程序。但是蹋盆,濫用靜態(tài)導(dǎo)入回是程序更難于都费薄,更難維護(hù)。會(huì)讓閱讀者很難弄清除其屬性或方法代表何意栖雾,甚至是哪一個(gè)類的屬性(方法)都要思考一番。(IDE友好提示是另說)

對于靜態(tài)導(dǎo)入伟众,一定要遵循兩個(gè)原則:
1.不使用*(星號)通配符析藕,除非是導(dǎo)入靜態(tài)常量類(只包含常量的類或接口)。
2.方法名是具有明確凳厢,清晰表象意義的工具類

不要在本類中覆蓋靜態(tài)導(dǎo)入的變量和方法

編譯器有一個(gè)“最短路徑”原則:如果能在奔雷中找到的變量账胧,常量竞慢,方法,就不會(huì)到其他包或者符類治泥,接口中查找筹煮,以確保奔雷中的屬性,方法優(yōu)先居夹。

如果要變更一個(gè)被導(dǎo)入的方法败潦,最好的辦法是在原始類中重構(gòu),而不是在本類中覆蓋准脂。

養(yǎng)成良好習(xí)慣劫扒,顯式聲明UID

類實(shí)現(xiàn)Serializable接口目的是為了可持久化,比如網(wǎng)絡(luò)傳輸或本地存儲(chǔ)狸膏,為系統(tǒng)的分布和異構(gòu)部署提供先決支持條件沟饥。若沒有序列化,現(xiàn)在我們熟悉的遠(yuǎn)程調(diào)用湾戳,對象數(shù)據(jù)庫都不可能存在贤旷。
通過SerialVersionUID,也叫做流標(biāo)識(shí)符,即類的版本定義的砾脑,它可以顯式聲明也可以隱式聲明幼驶。顯式聲明格式如下:
private static final long serialVersionUID = XXXXXL;
而隱式聲明是我不聲明,你編譯器在編譯的時(shí)候幫我生成拦止。

JVM在反序列化時(shí)县遣,會(huì)比較數(shù)據(jù)流中的serialVersionUID與類的serialVersionUID是否相同,如果相同汹族,則認(rèn)為類沒有發(fā)生改變萧求;如果不相同,JVM不干了顶瞒,拋個(gè)異常InvalidClassException夸政。

顯式聲明serialVersionUID可以提高代碼的健壯性。

~~## 避免用序列化類在構(gòu)造函數(shù)中為不變量賦值

避免為final變量復(fù)雜賦值

使用序列化類的私有方法巧妙解決部分屬性持久化問題~~

break萬萬不可忘

case后缺少break往往會(huì)稱為bug所在榴徐。
可以再IDE中做相應(yīng)的設(shè)置守问,將switch語句中,每個(gè)case不以break結(jié)尾的情況設(shè)置為編譯錯(cuò)誤坑资。

易變業(yè)務(wù)使用腳本語言編寫

例如我們項(xiàng)目中的公式耗帕。

慎用動(dòng)態(tài)編譯

動(dòng)態(tài)編譯一致是java的夢想,從Java6版本它開始支持動(dòng)態(tài)編譯了袱贮,可以在運(yùn)行期直接編譯.java文件仿便,執(zhí)行.class,并且能夠獲得相關(guān)的輸入輸出,甚至還能監(jiān)聽相關(guān)的事件嗽仪。

使用動(dòng)態(tài)編譯時(shí)需要注意以下幾點(diǎn):
1.在框架中謹(jǐn)慎使用
2.不要再要求高性能的項(xiàng)目使用
3.動(dòng)態(tài)編譯要考慮安全性問題
4.記錄動(dòng)態(tài)編譯過程荒勇。(空中編譯和運(yùn)行是很讓人不放心的,留下些一句可以更好地優(yōu)化程序)

避免instanceof非預(yù)期結(jié)果

public class Client {
    public static void main(String[] args) {
        //String對象是否是Object的實(shí)例
        boolean b1 = "Sting" instanceof Object;
        //String對象是否是String的實(shí)例
        boolean b2 = new String() instanceof String;
        //Object對象是否是String的實(shí)例
        boolean b3 = new Object() instanceof String;
        //拆箱類型是否是裝箱類型的實(shí)例
        boolean b4 = 'A' instanceof Character;
        //空對象是否是String的實(shí)例
        boolean b5 = null instanceof String;
        // 類型轉(zhuǎn)換后的空對象是否是String的實(shí)例
        boolean b6 = (String) null instanceof String;
        // Date對象是否是String的實(shí)例
        boolean b7 = new Date() instanceof String;
        // 在泛型類中判斷String對象是否是Date的實(shí)例
        boolean b8 = new GenericClass<String>().isDateInstance("");
    }
}

class GenericClass<T> {
    //判斷是否是Date類型
    public boolean isDateInstance(T t) {
        return t instanceof Date;
    }
}

'A' instanceof String無法編譯通過闻坚,因?yàn)?A'是一個(gè)char類型沽翔,也就是一個(gè)基本類型仅偎,不是一個(gè)對象,instanceof只能用于對象的判斷威恼,不能用于基本類型的判斷箫措。

不要只替換一個(gè)類

對于final修飾的基本類型和String類型,編譯器會(huì)認(rèn)為它是穩(wěn)定態(tài)(Immutable Status),所以在編譯時(shí)就直接把值變異到字節(jié)碼中了,編碼了在運(yùn)行期引用驾锰,以提高代碼的執(zhí)行效率。
對于final修飾的類(即非基本類型赏酥,編譯器認(rèn)為它是不穩(wěn)定態(tài)(Mutable Status))搬素,在編譯時(shí)簡歷的則是引用關(guān)系蔗蹋,如果Client類引入的常量是一個(gè)類或?qū)嵗词共恢匦戮幾g也會(huì)輸出最新值戒傻。

注意:發(fā)布應(yīng)用系統(tǒng)時(shí)禁止使用類文件替換方式艺挪,整個(gè)WAR包或者JAR包發(fā)布才是萬全之策口蝠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市眉反,隨后出現(xiàn)的幾起案子寸五,更是在濱河造成了極大的恐慌掰读,老刑警劉巖烁试,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拢肆,死亡現(xiàn)場離奇詭異减响,居然都是意外死亡靖诗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門支示,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刊橘,“玉大人,你說我怎么就攤上這事颂鸿〈倜啵” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵嘴纺,是天一觀的道長败晴。 經(jīng)常有香客問我,道長栽渴,這世上最難降的妖魔是什么尖坤? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮闲擦,結(jié)果婚禮上慢味,老公的妹妹穿的比我還像新娘。我一直安慰自己佛致,他們只是感情好贮缕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俺榆,像睡著了一般感昼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上罐脊,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天定嗓,我揣著相機(jī)與錄音,去河邊找鬼萍桌。 笑死宵溅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的上炎。 我是一名探鬼主播恃逻,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼藕施!你這毒婦竟也來了寇损?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤裳食,失蹤者是張志新(化名)和其女友劉穎矛市,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诲祸,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浊吏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年而昨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片找田。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歌憨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出午阵,到底是詐尸還是另有隱情躺孝,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布底桂,位于F島的核電站,受9級特大地震影響惧眠,放射性物質(zhì)發(fā)生泄漏籽懦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一氛魁、第九天 我趴在偏房一處隱蔽的房頂上張望暮顺。 院中可真熱鬧,春花似錦秀存、人聲如沸捶码。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惫恼。三九已至,卻和暖如春澳盐,著一層夾襖步出監(jiān)牢的瞬間祈纯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工叼耙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腕窥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓筛婉,卻偏偏與公主長得像簇爆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子爽撒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容