程序世界中這些神秘?cái)?shù)字你知道嗎

記得大學(xué)時(shí)看過一本書锅论,上邊寫到一個(gè)撩妹的小技巧:提出和對方玩一個(gè)意識(shí)游戲倾哺,讓她心中想一個(gè)1到10、對她而言比較有意義的一個(gè)數(shù)字寇荧,然后自己在另一個(gè)地方寫下一個(gè)數(shù)字举庶,往往能猜中。這個(gè)小技巧利用了人的心理揩抡,同時(shí)户侥,「程序」其本身本質(zhì)上就是數(shù)字镀琉,本文將收集一些有趣的數(shù)字,主要以Java語言中的數(shù)字為主蕊唐。給枯燥的生活一些調(diào)劑屋摔。

待會(huì)兒要登場的 Kim Polese

1. 神奇的數(shù)字 7142857

上邊的那個(gè)問題的答案是7。我們平時(shí)生活中總是會(huì)在各種各樣的地方遇到7這個(gè)數(shù)字替梨,當(dāng)你讓別人去想一個(gè)1到10的數(shù)字時(shí)钓试,它就歡呼雀躍地跳了出來。最廣為人知的就是「一周有7天」這個(gè)事情了副瀑,同時(shí)弓熏,7還可以延伸出來另外一個(gè)很有趣的數(shù)字142857,看下邊的算式:

1 / 7   =   0.142857, 142857, 142857...
2 / 7    =  0.285714, 285714...
3 / 7    =    0.428571...
4 / 7    =  0.571428...
5 / 7    =  0.714285...
6 / 7   =   0.857142...

當(dāng)我看到這個(gè)結(jié)果時(shí)已經(jīng)很震驚了糠睡,但是還有更多的:

著了魔的數(shù)字
142857 x 1 = 142857
142857 x 2 = 258714
142857 x 3 = 428571
142857 x 4 = 571428
142857 x 5 = 714285
148257 x 6 = 857142

2. 美劇「迷失」中的 4 8 15 16 23 42

這個(gè)太玄挽鞠,就不多說了。

「迷失」中的神秘?cái)?shù)字

3. 藏在Java隨機(jī)數(shù)中的hello world

這算是一個(gè)廣為人知的現(xiàn)象狈孔,在Java的Random類中實(shí)現(xiàn)的隨機(jī)數(shù)生成算法并不是真正的隨機(jī)數(shù)信认,只是概率上大致的隨機(jī),而其隨機(jī)性取決于種子的選取除抛,如果選取了特定的種子狮杨,那么產(chǎn)生的隨機(jī)數(shù)也就確定了。

色子才是真隨機(jī)

根據(jù)以上的事實(shí)到忽,把-229985452當(dāng)做種子傳入Random類橄教,就可以得到hello,相應(yīng)的-147909649則能得到world喘漏。在Java中執(zhí)行如下程序护蝶,它最終會(huì)打印輸出hello world

public static String randomString(int i) {
    Random ran = new Random(i);
    StringBuilder sb = new StringBuilder();
    while (true) {
        int k = ran.nextInt(27);
        System.out.println("char:" + k + ",number:" +  k);
        if (k == 0)
            break;
        k += 96;
        sb.append((char) k);
    }

    return sb.toString();
}
System.out.println(randomString(-229985452) + " " + randomString(-147909649));

根據(jù)這個(gè)原理翩迈,你可以找到很多字符串的種子持灰。原來除了簡單的編碼,字符串還可以使用隨機(jī)數(shù)的形式隱藏起來负饲。

4. JDK的版本號(hào)

我們知道的JDK版本號(hào)往往是1.6堤魁,1.8,或者Java8這種返十,但是在編譯后的class文件中并不是這么記錄的妥泉,偶爾在運(yùn)行程序時(shí)會(huì)碰到這個(gè)錯(cuò)誤

java.lang.UnsupportedClassVersionError: Bad version number in .class file [at java.lang.ClassLoader.defineClass1(Native Method)]

在class文件中版本號(hào)有[主版本號(hào)(major version number)].[次版本號(hào)(minor version number)],其中「主版本號(hào)」和「JDK版本號(hào)」的對應(yīng)關(guān)系如下所示:

  • Java SE 9 = 53 (0x35 hex),
  • Java SE 8 = 52 (0x34 hex),
  • Java SE 7 = 51 (0x33 hex),
  • Java SE 6.0 = 50 (0x32 hex),
  • Java SE 5.0 = 49 (0x31 hex),
  • JDK 1.4 = 48 (0x30 hex),
  • JDK 1.3 = 47 (0x2F hex),
  • JDK 1.2 = 46 (0x2E hex),
  • JDK 1.1 = 45 (0x2D hex).

5. class文件中的 0xcafebabe洞坑,或者說是3405691582

如果你用任何一個(gè)文本文檔編輯器打開一個(gè)Java的class文件或者M(jìn)ac平臺(tái)上的可執(zhí)行文件盲链,它的第一行一般如下所示:

//Java編譯后的class文件
cafe babe 0000 0034 0117 0700 0201 0012

//iOS平臺(tái)Objective-C編譯后的可執(zhí)行文件
cafe babe 0000 0005 0000 000c 0000 0009

其中第5、6個(gè)字節(jié)代表這個(gè)class文件的minor version number,這里全為0刽沾,第7本慕、8個(gè)字節(jié)代表major version number的值,52侧漓,代表我的版本是1.8锅尘。而前4個(gè)字節(jié)從最開始一直就是「CAFE BABE」,這個(gè)詞本來是 James Gosling對他經(jīng)常去的一個(gè)咖啡館火架,里的一個(gè)咖啡師的昵稱鉴象,后來陰差陽錯(cuò)的一致被沿用至今。

6. Mach-o文件中也有0xcafebabe

Mach-o是一種在某些平臺(tái)上(現(xiàn)在主要是Mac OS X和iOS)的可執(zhí)行文件類型何鸡,在上一節(jié)中的代碼中看到Objective-C編譯后的文件中也出現(xiàn)了0xcafebabe這個(gè)詞,這個(gè)詞的歷史其實(shí)可以追回到NeXT時(shí)期牛欢。

哈哈骡男,對,就是我的那個(gè)NeXT

在Unix/Linux中使用/etc/magic中定義的值來判定讀取到的文件類型(現(xiàn)在的Mac OS X中可以在/usr/share/file/magic目錄下找到)傍睹,就是說在程序讀取文件時(shí)隔盛,會(huì)根據(jù)讀到的前幾個(gè)字節(jié)進(jìn)行文件類型的判斷(而不是擴(kuò)展名),在Unix/Linux的系統(tǒng)中有個(gè)命令file可以判斷一個(gè)二進(jìn)制文件的類型拾稳。

NeXTSTEP是Mac OS X的前身吮炕,是一個(gè)基于BSD Unix的系統(tǒng),自然也遵循了這個(gè)方法访得,當(dāng)年NeXT獲取了Objective-C的使用權(quán)龙亲,同時(shí)開發(fā)了一整套的開發(fā)套件,那么就需要找一個(gè)值來指代其文件類型悍抑,于是就使用了0xcafebabe鳄炉,通常認(rèn)為是一位叫Mike DeMoney的哥們做的這個(gè)決定。

7. 怎么Mach-o和Java還有這層關(guān)系

差不多與此同時(shí)搜骡,Sun公司也在半秘密地開發(fā)著名的Oak項(xiàng)目拂盯,這個(gè)項(xiàng)目也選擇了0xcafebabe來作為魔術(shù)數(shù)。有一個(gè)有趣的故事是——這個(gè)有趣的故事好像是來源于Java項(xiàng)目的第一位工程師Patrick Naughton——cafe babe代表的是一個(gè)Sun公司的漂亮的市場經(jīng)理(就是開篇的那張照片记靡,Kim Polese)谈竿,她當(dāng)時(shí)在一個(gè)C++編譯器的項(xiàng)目中工作,那個(gè)項(xiàng)目叫做cafe(C++, A Front End)摸吠,于是她就被叫做cafe baby——在都是程序員的環(huán)境里大約就是會(huì)這樣——后來她調(diào)到了Oak項(xiàng)目空凸。話說后來Kim在硅谷也是風(fēng)生水起,現(xiàn)在是某公司CEO蜕便。下面來感受一下當(dāng)年的Kim劫恒。

高中時(shí)期
1996年創(chuàng)業(yè)時(shí)

當(dāng)然,一個(gè)好八卦必須要有很多版本。另一個(gè)說法是两嘴,NeXT的很多人后來不想跟喬幫主混了丛楚,去了FirstPerson公司,這些人在那里一手創(chuàng)立了Java——呃憔辫,當(dāng)然Java創(chuàng)始人公認(rèn)是James Gosling——但這些人確實(shí)對Java產(chǎn)生了很大的影響趣些。不得不承認(rèn),Java的設(shè)計(jì)理念和Objective-C有太多的相似之處(Interface屬于完全的抄……呃……借鑒)贰您,而且很多地方Java和Objective-C的設(shè)計(jì)理念相同坏平,只是由于拋掉了c語言的枷鎖,得以走得更遠(yuǎn)锦亦〔疤妫總之,他們來了杠园,然后這群人里有一個(gè)人(Mike DeMoney)使用了和Mach-o相同的魔術(shù)數(shù)顾瞪。

然而,八卦止于無聊的人(逃……)抛蚁,公認(rèn)的Java創(chuàng)始人James Gosling出來說:很抱歉打擾大家談?wù)摪素缘难排d陈醒,不過小可我才是那個(gè)選擇了在class文件中使用0xcafebabe的人,這跟上邊那幾位一點(diǎn)關(guān)系都沒有瞧甩。

As far as I know, I'm the guilty party on this one. I was totally unaware of the NeXT connection. The small number of interesting HEX words is probably the source of the match. As for the derivation of the use of CAFEBABE in Java, it's somewhat circuitous:

James大神

當(dāng)然钉跷,由這個(gè)magic number背后也可以看出Objective-C和Java一脈相承的關(guān)系。

8. 更多的魔術(shù)數(shù)

話說NeXT的這群工程師都好調(diào)皮肚逸。

0xbaaaaaad iOS錯(cuò)誤日志代碼爷辙,表示一個(gè)日志是全局日志快照,very bad
0xbad22222 iOS錯(cuò)誤日志代碼
0x8badf00d (Ate Bad Food) iOS錯(cuò)誤日志代碼吼虎,表示代碼吃壞了肚子犬钢,被殺掉了
0xdeadfa11 (Dead Fall) iOS錯(cuò)誤日志代碼,用戶強(qiáng)制退出
0xDEAD10CC (Dead Lock) iOS錯(cuò)誤日志代碼思灰,這個(gè)很清晰玷犹,哎呀,死鎖了
0xBAADF00D (Bad Food) Windows中的錯(cuò)誤代碼
0xCAFED00D (Cafe dude) Java中使用
0xCAFEBABE (Cafe babe) Java和Mach-o文件類型
0x0D15EA5E (Disease) 
0x1BADB002 (1 bad boot) 啟動(dòng)失敗
0xDEADDEAD Windows的藍(lán)屏洒疚?歹颓??

9. Integer類型中的-128和127

很多書油湖、文章或者各種編程指南中都建議在Java中不要使用基本數(shù)據(jù)類型(int巍扛,longchar乏德,byte等)撤奸,Java也提供了自動(dòng)裝箱來盡可能的保證在JVM中奔跑的數(shù)據(jù)盡可能都是「對象」吠昭。然而,有時(shí)候這種習(xí)慣也會(huì)帶來一些副作用胧瓜。

for (int i = 0; i < 10; i++) {
    System.out.println((Integer) i);
}
//正常情況下矢棚,此代碼會(huì)循環(huán)輸出0到9等十個(gè)數(shù)字

但是,我們可以通過一些小手段府喳,使這個(gè)代碼輸出其他的數(shù)字蒲肋。利用到Java的兩個(gè)特性,反射和Integer類的緩存钝满。

大家都知道兜粘,當(dāng)你在Java中獲取-128到127的Integer類型時(shí),其實(shí)是不會(huì)新建對象的弯蚜,很多面試題都喜歡考這個(gè)特性孔轴,其實(shí)沒什么高深的,只是想給人挖陷阱而已碎捺。Integer類有一個(gè)內(nèi)部類叫IntegerCache距糖,在這個(gè)類中創(chuàng)建了256個(gè)數(shù)字的緩存,在JDK的源碼中是這樣寫的:

public static Integer valueOf(int i) {
    //這里的low和high就是-128和127牵寺,也就是一個(gè)字節(jié)的長度
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

針對上邊這塊代碼,我只要把這個(gè)靜態(tài)內(nèi)部類IntegerCache中的cache數(shù)組的內(nèi)容改掉恩脂,別人再調(diào)用valueOf()就拿不到正確的數(shù)據(jù)了帽氓,代碼如下:

Class<?> clazz = Class.forName("java.lang.Integer$IntegerCache");
Field field = clazz.getDeclaredField("cache");
field.setAccessible(true);
Integer[] cache = (Integer[]) field.get(clazz);

// 寫入錯(cuò)誤的值
for (int i = 0; i < cache.length; i++) {
  cache[i] = new Integer(128 - i);
}

10. ArrayList的默認(rèn)大小

使用Java集合時(shí),有時(shí)候因?yàn)椴幌M龅?code>null的情況俩块,所以一些List會(huì)像這樣賦值

List<String> list = new ArrayList<>();

這條語句的意思是建立一個(gè)默認(rèn)為空的ArrayList黎休,但是Java的ArrayList的空間是自增的,且ArrayList底層是用數(shù)組實(shí)現(xiàn)的玉凯,所以就會(huì)有一個(gè)默認(rèn)大小势腮,作為第一次需要自增時(shí)初始化的大小,這個(gè)數(shù)字在ArrayList而言是10漫仆。所以如果你使用上邊的語句建立List捎拯,那么在第一次插入元素時(shí),它就會(huì)生成一個(gè)空間為10的數(shù)組盲厌。如果你這個(gè)List最多只會(huì)插入4個(gè)元素署照,那么就浪費(fèi)了空間。所以如果要建立的這個(gè)List大小大約已知的話吗浩,在性能需求較緊張時(shí)建芙,最好把你預(yù)測的空間填進(jìn)去。

當(dāng)然懂扼,不要過早去優(yōu)化禁荸,但一個(gè)好習(xí)慣總是好的右蒲。

最后編輯于
?著作權(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級(jí)特大地震影響急灭,放射性物質(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)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)钙蒙,斷路器茵瀑,智...
    卡卡羅2017閱讀 134,599評論 18 139
  • 姓名:周君會(huì) 學(xué)號(hào):17011210526 轉(zhuǎn)載自: http://www.reibang.com/p/...
    lotus兒閱讀 1,935評論 1 9
  • 少用挑剔眼光看待孩子成長马昨,相比較,國外家長則習(xí)慣用欣賞的眼光看待自己扛施、孩子和世界鸿捧。 有位教育專家曾經(jīng)談到這樣一個(gè)奇...
    書宇YY閱讀 297評論 0 0
  • 我熱愛的少女 愛幻想的少女 幻想把鐵軌還給海子 幻想把斧頭還給顧城 為這詩與遠(yuǎn)方 我痛飲般若湯 酒醉帶出鐵軌和斧頭...
    鴻清風(fēng)閱讀 231評論 0 0
  • 我們常常把“來日方長”掛在嘴邊笛谦,以為日子還很長。 很遺憾昌阿,時(shí)光總在一句沒有定數(shù)的承諾中溜走饥脑。 而我們,也這樣錯(cuò)過了...
    YanwayLin閱讀 716評論 0 1