小知識|Java中的"魔數"

喝水會長肉發表於2021-12-14

在程式設計過程中,我們可能經常聽到“魔數”這個詞,那麼這個詞到底指的是什麼呢?什麼數叫做魔數呢?

一、標識檔案型別的“魔數”

大多數情況下,我們都是通過副檔名來識別一個檔案的型別的,比如我們看到一個 .txt型別的檔案我們就知道他是一個純文字檔案。但是,副檔名是可以修改的,那一旦一個檔案的副檔名被修改過,那麼怎麼識別一個檔案的型別呢。這就用到了我們提到的“魔數”。

很多型別的檔案,其起始的幾個位元組的內容是固定的(或是有意填充,或是本就如此)。因此這幾個位元組的內容也被稱為魔數 (magic number),因為根據這幾個位元組的內容就可以確定檔案型別。有了這些魔術數字,我們就可以很方便的區別不同的檔案。

為了方便虛擬機器識別一個檔案是否是class型別的檔案,SUN公司規定每個class檔案都必須以一個word(四個位元組)作為開始,這個數字就是魔數。魔數是由四個位元組的無符號陣列成的,而class檔案的名字還挺好聽的的,其魔數就是 0xCAFEBABE

讀者可以隨便編譯一個class檔案,然後然後用十六進位制編輯器開啟編譯後的class檔案,基本格式如下:

如何使用16進位制開啟class檔案:使用 vim test.class ,然後在互動模式下,輸入:%!xxd 即可。

二、程式碼中的魔數

在有些程式碼中,有一些數字常量或者字串,他們沒有註釋,並且從命名上也看不出什麼意思,很可能在過一段時間之後誰也不知道這個常量或者字串代表什麼意思。我們就稱這個常量或者字串為魔數。

在《阿里巴巴Java開發手冊》中也有關於魔數的要求:

在程式碼中使用魔數,不僅使程式碼的可讀性大大降低,還可能導致各種問題。所以在程式碼中,我們要儘量避免產生魔數。

所有需要使用魔數的地方,都可以使用列舉或者靜態變數來代替。

譬如一個很簡單的根據職位計算薪水的方法


public int 
getSalary
(
String title, int grade
) 
{

    if ( "Programmer" . equals (title ) ) {
        return grade * 500 + 700 ;
    }

    else if ( "Tester" . equals (title ) ) {
        return grade * 500 + 800 ;
    }
//java學習交流:737251827  進入可領取學習資源及對十年開發經驗大佬提問,免費解答!
    else if ( "Analyst" . equals (title ) ) {
        return grade * 800 + 1000 ;
    }
}

在這個方法裡面,"Programmer","Tester"和"Analyst"是所謂的魔字串(Magic String),而500, 700,800和1000就是所謂的魔數(Magic Number)了。 咋一看,程式碼這樣寫也沒有什麼問題,但是,仔細思考一下就會發現,如果這種隨手捻來的字串和數字散佈於程式當中,隨處可見的話,是會有很多弊病的。

如果我們使用常量來代替上面的魔數的話,程式碼就會清爽很多,而且,下次修改的時候只需要修改常量值就可以了。


public int 
getSalary
(
String title, int grade
) 
{

    if (Constants . TITLE_PROGRAMMER . equals (title ) ) {
        return grade * Constants . BASE_SALARY_LOW + Constants . ALLOWANCE_LOW ;
    }
    else if (Constants . TITLE_TESTER . equals (title ) ) {
        return grade * Constants . BASE_SALARY_LOW + Constants . ALLOWANCE_MEDIUM ;
    }
    else if (Constants . TITLE_ANALYST . equals (title ) ) {
        return grade * Constants . BASE_SALARY_HIGH + Constants . ALLOWANCE_HIGH ;
    }

}



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010294/viewspace-2847677/,如需轉載,請註明出處,否則將追究法律責任。

相關文章