Java基礎---Stackoverflow上人氣最旺的10個Java問題

1、 爲什麼兩個(1927年)時間相減得到一個奇怪的結果?

(3623個贊)

如果執行下面的程序,程序解析兩個間隔1秒的日期字符串並比較:

[java] view plaincopy
  1. public static void main(String[] args) throws ParseException {  
  2.     SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    
  3.     String str3 = "1927-12-31 23:54:07";    
  4.     String str4 = "1927-12-31 23:54:08";    
  5.     Date sDt3 = sf.parse(str3);    
  6.     Date sDt4 = sf.parse(str4);    
  7.     long ld3 = sDt3.getTime() /1000;    
  8.     long ld4 = sDt4.getTime() /1000;  
  9.     System.out.println(ld4-ld3);  
  10. }  

輸出是:353

爲什麼 ld4-ld3 不是1(因爲我希望這兩個時間差是一秒),而是353?

如果將日期字符串各加一秒:

[java] view plaincopy
  1. String str3 = "1927-12-31 23:54:08";    
  2. String str4 = "1927-12-31 23:54:09";  

ld4-ld3 的結果是1.

[java] view plaincopy
  1. sun.util.calendar.ZoneInfo[id="Asia/Shanghai",  
  2. offset=28800000,dstSavings=0,  
  3. useDaylight=false,  
  4. transitions=19,  
  5. lastRule=null]  
  6.    
  7. Locale(Locale.getDefault()): zh_CN  

解決方案

這是上海時區在12月31日有一個變化。

查閱這個網址來了解上海在1927年時區變化的細節。基本上在1927年年底的午夜,始終會回撥5分52秒。所以“1927-12-31 23:54:08”實際上發生了兩次,看起來Java解析了後一次的時間作爲當地的日期和時間導致了差異。

PS:親測第一個例子是1啊。。。。。。。。。

(2480個贊)

我一直認爲Java是引用傳遞;然而,我看了一堆博客(例如這篇)聲稱不是這樣的。我認爲我沒有理解它們之間的區別。

給個解釋?

解決方案

Java一直是值傳遞。不幸的是,他們決定把指針叫做引用,因此新人總是被搞暈。因爲這些引用也是通過值傳遞的。

PS:面試被問過。。。

3、一個關於Java += 操作符的問題

(2223贊)

直到今天我認爲這個例子:

[java] view plaincopy
  1. i += j;  
只是一個簡寫的:

[java] view plaincopy
  1. i = i + j;  
但如果這樣做:

[java] view plaincopy
  1. int i = 5;  
  2. long j = 8;  

然而 i = i + j; 沒法編譯,而 i += j; 就可以編譯。

這意味着i += j; 實際上是i = (type of i) (i + j)的簡寫麼?

解決方案

總有人問這類問題,JLS裏有答案。參見 §15.26.2複合賦值運算符。摘錄:

E1 op= E2 型的複合賦值表達式等價於 E1 = (T)((E1) op (E2)),這裏 T 是 E1 的類型,不同的是 E1 只計算一次。

一個例子,引自 §15.26.2

[...] 下面的代碼是正確的:

[java] view plaincopy
  1. short x = 3;  
  2. x += 4.6;  

x的結果等於7,因爲它等價於:

[java] view plaincopy
  1. short x = 3;  
  2. x = (short)(x + 4.6);  

換句話說,你的假設是正確的。

PS:面試被問過。。。

(1769個贊)

Java中 HashMap 和 Hashtable的不同是什麼?

非多線程應用中使用哪個更有效率?

解決方案

Java 中 HashMap 和 HashTable 有幾個不同點:

  1. Hashtable 是同步的,然而 HashMap不是。 這使得HashMap更適合非線程應用,因爲非同步對象通常執行效率優於同步對象。
  2. Hashtable 不允許 null 值和鍵。HashMap允許有一個 null 鍵和人一個 NULL 值。
  3. HashMap的一個子類是LinkedHashMap。所以,如果想預知迭代順序(默認的插入順序),只需將HashMap轉換成一個LinkedHashMap。用Hashtable就不會這麼簡單。

因爲同步對你來說不是個問題,我推薦使用HashMap。如果同步成爲問題,你可能還要看看ConcurrentHashMap

PS:面試必問。。。

(1724個贊)

如果你有一個 java.io.InputStream 對象,如處理這個對象並生成一個字符串?

假定我有一個 InputStream 對象,它包含文本數據,我希望將它轉化成一個字符串(例如,這樣我可以將流的內容寫到一個log文件中)。

InputStream 轉化成 String 最簡單方法是什麼?

解決方案

使用 Apache commons IOUtils庫來拷貝InputStream到StringWriter是一種不錯的方式,類似這樣:

[java] view plaincopy
  1. StringWriter writer = new StringWriter();  
  2. IOUtils.copy(inputStream, writer, encoding);  
  3. String theString = writer.toString();  
甚至

[java] view plaincopy
  1. // NB: does not close inputStream, you can use IOUtils.closeQuietly for that  
  2. // 注意:不關閉inputStream,你可以使用 IOUtils.closeQuietly  
  3. String theString = IOUtils.toString(inputStream, encoding);  

或者,如果不想混合Stream和Writer,可以使用 ByteArrayOutputStream。

(1574個贊)

在Swing中,密碼字段有一個getPassword()(返回 char數組)方法而不是通常的getText()(返回String)方法。同樣的,我遇到過一個建議,不要使用 String 來處理密碼。

爲什麼String涉及到密碼時,它就成了一個安全威脅?感覺使用char數組不太方便。

解決方案

String是不可變的。這意味着一旦創建了字符串,如果另一個進程可以進行內存轉儲,在GC發生前,(除了反射)沒有方法可以清除字符串數據。

使用數組操作完之後,可以顯式地清除數據:可以給數組賦任何值,密碼也不會存在系統中,甚至垃圾回收之前也是如此。

所以,是的,這是一個安全問題 – 但是即使使用了char數組,僅僅縮小了了攻擊者有機會獲得密碼的窗口,它值針對制定的攻擊類型。

7、遍歷HashMap的最佳方法

(1504個贊)

遍歷HashMap中元素的最佳方法是什麼?

解決方案

這樣遍歷entrySet

[java] view plaincopy
  1. public static void printMap(Map mp) {  
  2.     Iterator it = mp.entrySet().iterator();  
  3.     while (it.hasNext()) {  
  4.         Map.Entry pair = (Map.Entry)it.next();  
  5.         System.out.println(pair.getKey() + " = " + pair.getValue());  
  6.         it.remove(); // avoids a ConcurrentModificationException  
  7.     }  
  8. }  

更多請查閱Map

PS:面試必問。。。京東二面被問過,還有其他公司,竟然現在才知道。

8、(如何)從數組創建ArrayList

(1468個贊)

我有一個數組,初始化如下:

[java] view plaincopy
  1. Element[] array = {new Element(1), new Element(2), new Element(3)};  

我希望將這個數組轉化成一個ArrayList類的對象。

解決方案

[java] view plaincopy
  1. new ArrayList<Element>(Arrays.asList(array))  

(1478個贊)

我有過一個面試,被問到如何產生一個Java內存泄露。不用說,我感到相當傻,甚至如何產生一個的線索都沒有。

那麼怎麼才能產生一個內存泄露呢?

解決方案

在純Java中,有一個很好的方式可以產生真正的內存泄露(通過執行代碼使對象不可訪問但仍存在於內存中):

  1. 應用產生一個長時間運行的線程(或者使用一個線程池加速泄露)。
  2. 線程通過一個(可選的自定義)類加載器加載一個類。
  3. 該類分配大內存(例如,new byte[1000000]),賦值給一個強引用存儲在靜態字段中,再將它自身的引用存儲到ThreadLocal中。分配額外的內存是可選的(泄露類實例就夠了),但是這樣將加速泄露工作。
  4. 線程清除所有自定義類的或者類加載器載入的引用。
  5. 重複上面步驟。

這樣是有效的,因爲ThreadLocal持有對象的引用,對象持有類的引用,接着類持有類加載器的引用。反過來,類加載器持有所有已加載類的引用。這會使泄露變得更加嚴重,因爲很多JVM實現的類和類加載都直接從持久帶(permgen)分配內存,因而不會被GC回收。

(1422個贊)

我試着使用Java生成一個隨機整數,但是隨機被指定在一個範圍裏。例如,整數範圍是5~10,就是說5是最小的隨機值,10是最大的。5到10之間的書也可以是生成的隨機數。
解決方案

標準的解決方式(Java1.7 之前)如下:

[java] view plaincopy
  1. import java.util.Random;  
  2.    
  3. public static int randInt(int min, int max) {  
  4.    
  5.     Random rand;  
  6.     int randomNum = rand.nextInt((max - min) + 1) + min;  
  7.    
  8.     return randomNum;  
  9. }  

請查看相關的JavaDoc。在實踐中,java.util.Random 類總是優於 java.lang.Math.random()

特別是當標準庫裏有一個直接的API來完成這個工作,就沒有必要重複製造輪子了。

原文鏈接: nolsit 翻譯: ImportNew.com liken
譯文鏈接: http://www.importnew.com/16841.html
轉載請保留原文出處、譯者和譯文鏈接。]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章