Java Detail

From http://www.importnew.com

1. String:

1) == and equals

String對象會創建一個字符串池(a pool of string),如果當前備新創建的字符串對象的值在這個池子中已經存在,那麼就不會生成新對象,而是複用池已有的字符串對象。flyweight 模式的精髓就是對象複用。不過,只有採用Object s = “Hello”方式(而非用”new“關鍵字)聲明String對象的時候這個規則纔會被應用。

Object s1 = new String("Hello");
Object s2 = new String("Hello");
  == --> false

Object s1 = "Hello";
Object s2 = "Hello";
== --> true
2)字符串對象(String Object)是非可變的

String s = " Hello ";
s += " World ";
s.trim( );
System.out.println(s);
trim() not works. Need s= s.trim();

3)替換String‘+’操作改爲循環調用StringBuffer.Append()。
2.多線程

1) 進程和線程的區別:一個進程對應一個程序的執行,而一個線程則是進程執行過程中的一個單獨的執行序列,一個進程可以包含多個線程。線程有時候也被稱爲輕量級進程.

2)一個Java虛擬機的實例運行在一個單獨的進程中,不同的線程共享Java虛擬機進程所屬的堆內存。這也是爲什麼不同的線程可以訪問同一個對象。線程彼此共享堆內存並保有他們自己獨自的棧空間。這也是爲什麼當一個線程調用一個方法時,他的局部變量可以保證線程安全。但堆內存並不是線程安全的,必須通過顯示的聲明同步來確保線程安全。

3)幾種不同的創建線程的方法:

•  繼承Thread 類
•  實現Runnable 接口
•  使用Executor framework (這會創建一個線程池)
4)同步:當某個方法或者代碼塊被聲明爲”synchronized”後,保存數據的內存空間(例如堆內存)將保持被同步狀態。
這意味着:當一個線程獲取鎖並且執行到已被聲明爲synchronized的方法或者代碼塊時,該線程首先從主堆內存空間中讀取該鎖定對象的所有變化,以確保其在開始執行之前擁有最新的信息。在synchronized部分執行完畢,線程準備釋放鎖的時候,所有針對被鎖定對象的修改都將爲寫入主堆內存中。這樣其他線程在請求鎖的時候就可以獲取最新的信息。

3.final關鍵字:

1)final成員變量必須在聲明的時候初始化或者在構造器中初始化,否則就會報編譯錯誤。

2)你不能夠對final變量再次賦值。final方法不能被重寫。final類不能被繼承。按照Java代碼慣例,final變量就是常量

3)在匿名類中所有變量都必須是final變量。

4) 對於集合對象聲明爲final指的是引用不能被更改,但是你可以向其中增加,刪除或者改變內容。

4. HashMap:

1)HashMap and Hashtable: 

a.HashMap可以接受null鍵值和值,而Hashtable則不能;

b.HashMap是非synchronized;HashMap很快( sychronized意味着在一次僅有一個線程能夠更改Hashtable。就是說任何線程要更新Hashtable時要首先獲得同步鎖,其它線程要等到同步鎖被釋放之後才能再次獲得同步鎖更新Hashtable); 

c.HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以當有其它線程改變了HashMap的結構(增加或者移除元素),將會拋出ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會拋出ConcurrentModificationException異常。

2)Hashtable和ConcurrentHashMap:都可以用於多線程的環境,在迭代的過程中,ConcurrentHashMap僅僅鎖定map的某個部分,而Hashtable則會鎖定整個map。當Hashtable的大小增加到一定的時候,性能會急劇下降,因爲迭代時需要被鎖定很長的時間。

3)給put()方法傳遞鍵和值時,我們先對鍵調用hashCode()方法,返回的hashCode用於找到bucket位置來儲存Entry對象。

4)因爲hashcode相同,所以它們的bucket位置相同,‘碰撞’會發生。因爲HashMap使用鏈表存儲對象,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在鏈表中。

5)找到bucket位置之後,會調用keys.equals()方法去找到鏈表中正確的節點,最終找到要找的值對象。完美的答案.

6)默認的負載因子大小爲0.75,也就是說,當一個map填滿了75%的bucket時候,和其它集合類(如ArrayList等)一樣,將會創建原來HashMap大小的兩倍的bucket數組,來重新調整map的大小,並將原來的對象放入新的bucket數組中。這個過程叫作rehashing,因爲它調用hash方法找到新的bucket位置。

7)當重新調整HashMap大小的時候,確實存在條件競爭,因爲如果兩個線程都發現HashMap需要重新調整大小了,它們會同時試着調整大小。在調整大小的過程中,存儲在鏈表中的元素的次序會反過來,因爲移動到新的bucket位置的時候,HashMap並不會將元素放在鏈表的尾部,而是放在頭部,這是爲了避免尾部遍歷(tail traversing)。如果條件競爭發生了,那麼就死循環了。這個時候,你可以質問面試官,爲什麼這麼奇怪,要在多線程的環境下使用HashMap呢.HashMap不能保證隨着時間的推移Map中的元素次序是不變的。

N.Coding Style:

1)Avoid Null Pointer:

a.在取得列表的時候,如果返回的結果是空的話,最好返回一個長度爲0的集合或者數組,而不要返回null。因爲,返回null的話可能能會導致程序錯誤。

b. 從已知的非空String對象中調用equals()方法

c.因爲調用null對象的toString()會拋出空指針異常,如果我們能夠使用valueOf()獲得相同的值,那寧願使用valueOf(),傳遞一個null給valueOf()將會返回“null”,尤其是在那些包裝類,像Integer、Float、Double和BigDecimal。

d.你可以使用StringUtils.isBlank(),isNumeric(),isWhiteSpace()以及其他的工具方法而不用擔心空指針異常。

2)Java中方法的返回值:通過自定義類提供多個返回值。相比使用數組、集合或元組結構,大大提高代碼的可讀性和流暢性。



發佈了9 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章