关于Java的10个谎言
以下的這些都算是比較高級的問題了。面試中一般也非常少問到。由于它們可能會把面試者拒之門外。只是你能夠自己找個時間來實踐一下。
System.exit(0)會跳過finally塊的運行
System.setSecurityManager(new SecurityManager() {@Overridepublic void checkExit(int status) {throw new ThreadDeath();}});try {System.exit(0);} finally {System.out.println("In the finally block");}
| System?.?setSecurityManager?(?new?SecurityManager?(?)?{ @?Override public?void?checkExit?(?int?status?)?{ throw?new?ThreadDeath?(?)?; } }?)?; try?{ System?.?exit?(?0?)?; }?finally?{ System?.?out?.?println?(?"In the finally block"?)?; } |
這段代碼為什么會輸出In the finally block?為什么沒有打印出堆棧跟蹤信息呢? 2. String str = “Hello”;當中str是一個字符串對象 跟C++不同的是,Java里的變量要么是基礎類型,要么是引用。變量不可能是對象。這意味著像這種表達式:
String str = "Hello";String text = "Bye";str == text; // 比較兩個引用。而不是內容str = text; // 把text的引用賦值給str
| String?str?=?"Hello"?; String?text?=?"Bye"?; str?==?text?;?// 比較兩個引用,而不是內容 str?=?text?;?// 把text的引用賦值給str |
大多數情況下事實上沒有太大的差別,只是這么寫easy引起困惑。
final StringBuilder sb = new StringBuidler();sb.append("Hello"); // 這個引用是final類型的,而不是這個實例。 method(sb); // 能夠通過方法來改動這個實例。只是這個變量是無法改動的
| final?StringBuilder?sb?=?new?StringBuidler?(?)?; sb?.?append?(?"Hello"?)?;?// 這個引用是final類型的。而不是這個實例。 method?(?sb?)?;?// 能夠通過方法來改動這個實例,只是這個變量是無法改動的 |
- Java的內存泄露跟C++程序猿理解的一樣 內存泄露在維基百科上的定義是”在計算機科學中,假設程序沒有正確地管理好內存分配 ,就會出現內存泄露。在面向對象編程中,假設內存中的一個對象無法在代碼中訪問不到的話。這就是內存泄露。” 只是在Java中,對象總是可達的,那些沒有強引用的對象會被清除掉。
內存泄露這個術語在Java中意味著:內存中存在著不該存在的對象,通常來說是有些不再使用的資源卻仍存儲在集合中。
- 多線程編程非常難 假設你沒有經驗的話。多線程編程的確非常難。假設你僅僅是把一堆代碼扔到一堆線程中去運行,那樣出了問題根本沒法解決,僅僅能是一團糟。 但假設你能進行線程的按需分配。控制線程間的交互。使用一些團隊中的成員也能明確的簡單的模式,問題就變得簡單多了。當然另一個挑戰就是你得讓團隊中的全部人都遵循你的這個規則:-)
- 不用關心不同操作間性能的不同 近期聽說有個問題,它涉及到了整數的相加,內存訪問。取模,以及輸出到控制臺。
雖然在這些操作里面,每個都比前面一個要慢一個數量級,但這哥們就是想優化這里面最快的操作,加法,還用了些更昂貴的操作來替換它。 假設你真的想要優化性能,你最好用一個便宜的操作來替換掉那些昂貴的操作,假設你的瓶頸在硬件這塊,例如說要從硬盤里面讀取大量的文件。改動軟件的代碼是沒啥用了,由于問題根本 就不在這。
- 隨機數都是隨機的
一組特定的隨機數就像是某種模式的數字。這個問題我在?這篇文章?中已經講到過了。
非常多人都不相信隨機數生成器生成的數字事實上是不隨機的。
- 應該盡量避免使用浮點數,由于它們會產生隨機錯誤
對于同一個操作而言。浮點數每次都會產生相同的錯誤。錯誤是可預測的,因此也是可控的。假設你清楚你要做的事情是什么,并且堅持使用一些簡單的規則,比方說對結果進行舍入操作。那么浮點數出的錯也不會比BigDecimal要多。除此之外它的可讀性更強,并且效率快了百倍以上(同一時候產生的垃圾對象也更少了)。
- 時區是永恒不變的
之所以會有這個誤解是由于,隨著時間的變化,時區是在改變的。這意味著歐洲/倫敦在新紀元的時候是1970/1/1 01:00而不是00:00,為什么?由于倫敦在1968年到1971年這兩年間的時間內使用的是夏令時。
在過去的這些年里面,還有不少時區也發生了變化。莫斯科曾經是東三區(GMT+3),如今是東四區(GMT+4)(從2011年3月27日開始)。
假設你看下2010年的時間,你會發現它是東三區而不是東四區。
還有些事你聽起來也許會感覺非常意外:
- 1721年的瑞典的2月有30天。
- 1751年英格蘭的第一天是3月25日,和法國相比差了11天。
- 美國採用公歷紀年后。它往前追溯了上百年,這樣原先記錄的那些日期都能夠用兩種日歷來進行表示(通常為了更精確會同一時候提供兩個日期)。
比方喬治華盛頓的生日從1731年2月11變成了1732年2月22。
- 當你在線程中讀取一個非volatile變量時,你終于能讀取它更新的那個值。
前幾天這個問題在StackOverflow上出現過兩回了。一般來說,JIT編譯器優化代碼的時候會將這個線程沒有改動到的非volatile類型的字段進行內聯。
一旦這個代碼被編譯了(你能夠通過-XX:+PrintCompilation看到),你在還有一個線程對這個字段進行的改動它非常可能就永遠也看不到了。
加上隨機的同步塊或者打印語句能夠推遲這個優化的運行,或者擾亂JIT編譯器。讓它不去運行這個優化。
- Java面試題都是正確的
有非常多Java面試題要么是過時了(超過10年沒有更新了,和如今的Java版本號已經脫節),要么是誤導大家的,甚至可能是錯的。不幸的是這些答案都沒有檢查過就被到處傳來傳去。
我會參考Stackoverflow上面的答案,由于這里的答案同行審查做的更好些。總的來說,像rose india這種站點就不要上了。上面的答案的質量差的離譜。假設你喜歡刨根究底的話,能夠看看上面一篇文章里有多少拼寫錯誤(類名以及專業術語)或者錯誤的言論。存在這些問題的一個原因在于沒有一個有效的反饋機制來糾正這些錯誤。
文章來自:?http://it.deepinmind.com/java/2014/05/10/common-java-myths.html
轉載于:https://www.cnblogs.com/clnchanpin/p/7008060.html
總結
以上是生活随笔為你收集整理的关于Java的10个谎言的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中的基本数据类型以及Java的基
- 下一篇: #51CTO学院四周年#其实、其实,我就