這篇文章收集了一些面試常見的JAVA觀念考題,可以簡單問出應徵者對於物件導向、執行緒等觀念。
2016.04.15 新增StringBuffer/StringBuilder的比較
- Java基本的Collection有哪些?
- Colleciton: 一群物件
- Set: 無序的collection且不允許重複元素
- List: 有序的collection且允許出現相同的元素
- Map: 無序的collection,包含key及相對應的value,特別注意key不允許重複
- HashTable跟HashMap的差異
HashTable | HashMap | |
允許null key/value | 不行 | 可以 |
是否Synchronize | 是 | 否 |
取值的方法 | contains | containsValue及containsKey |
- 如何實作Synchronized HashMap
Map map = Collections.synchronizedMap(new HashMap());
- Iterator跟ListIterator的差異
- Iterator可以用來traverse Set及List,ListIterator只能用在List
- Iterator只能往前traverse,ListIterator可以雙向
- ListIterator時做了Iterator介面並且增加函數
- Iterator中的fail-fast跟fail-safe是甚麼?
- fail-fast: iteration開始時只要Collection的內容被改動就會拋出ConcurrentModificationException,java.util裡面都屬於fail-fast
- fail-safe: java.util.concurrent package裡面的Class都是(例如CopyOnWriteArrayList),不會拋出ConcurrentModificationException
- Arrays跟ArrayList的差異
- Arrays可包含原始(primitive)及物件(object),ArrayList只允許物件
- Arrays大小固定,ArrayList可以動態調整
- ArrayList提供較多方法,如removeAll、iterator
- a == b 以及 a.equals(b)有何差異
- a == b只有在兩者指向記憶體中同一個stack對象時才會為真,a.equals(b)則是邏輯比較,例如String.equals()可用來比較兩個不同物件所含的相同字串內容
- Constructor是否可以被Override?
- 構造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading
- 甚麼是Singleton,如何實作?
- Singleton模式主要作用是保證在Java應用程式中,一個Class只有一個Instance存在
public class MySingleton{ private static MySingleton uniqueInstance; private MySingleton(){} // 使用Private以確保mySingleton 只能透過 API:getInstance() 產生Instance public static synchronized MySingleton getInstance() { if(uniqueInstance == null ) {uniqueInstance = new mySingleton();} return uniqueInstance; } }
- 說明Interface、Abstract、Anonymous Class
- Interface: Java 的介面 (interface) 是一種參考型態 (reference type) ,使用關鍵字 interface 宣告及定義,同時 interface 已隱含 abstract ,介面中通常會定義的常數 (constant) 及方法 (method) ,其方法必須由類別 (class) 所實作 (implement)
- Abstract: 使用關鍵字 abstract 宣告的類別 (class) 並不能夠被實體化 (instantiated) ,也就是說不能用 abstract 的類別建立物件 (object) ,但abstract 類別可當成父類別 (superclass) 給子類別 (subclass) 繼承 (inherit) 。
- Anonymous Class: 匿名類別實際上也擁有一個.class檔案,在概念上,它其實就是將一個類別或是介面在編譯new statement時由編譯器重新產生出另一個類別
- 說明Generic(泛型)
- 由於 Java 有嚴格的型態限制,因此成員 (member) 宣告為那一種型態,就只能使用該種型態的資料,後來 Java 5.0 後加入了泛型 (generic) 的特性,使型態使用可以具有某種彈性。
List<Stirng> list = new ArrayList<String>();
- sleep()跟wait()的差異
- sleep()是使線程停止一段時間的方法。在sleep 時間間隔期滿後,線程不一定立即恢復執行。這是因為在那個時刻,其他線程可能正在運行而且沒有被設定為放棄執行,除非(a)“醒來”的線程具有更高的優先順序 (b)正在運行的線程因為其他原因而阻塞。
- wait()是線程交互時,如果線程對一個同步物件x 發出一個wait()調用,該線程會暫停執行,被調物件進入等待狀態,直到被喚醒或等待時間到。
(Cited: JavaMadeSoEasy.com)
- 說明stack跟heap
- stack: 可被預測生命週期的變數或函數資訊都放在stack,例如區域變數(local variable)、函式參數(function/method parameter)、函數的返回位址(function/method return address)等資訊
- heap: 動態配置的記憶體空間,放置被new出來的物件以及內含的成員變數及方法
一般來說stack爆掉是因為有太多區域變數或recursive function跑太深,heap爆掉則是GC沒有做好物件無法被回收
- 說明Java8的Lambda
使用Lambda來取代以往Functional Interface的使用方式,可以大大的縮短程式碼,在編譯的過程中,也可以避免掉產生新的.class檔案出來,執行的時候,也不會再重新new出一個物件實體,而是直接將Lambda的body程式碼存放在記憶體,直接以類似call function的方式去執行,大大的提升程式的執行效能。
//Example 1: new Runnable Runnable run = new Runnable() { public void run() { System.out.println("run me!"); } }; // one line lambda Runnable run = () -> System.out.println("run me!"); // Exmaple 2: Iterate Map Set keySet = map.keySet(); for (String s : keySet) { System.out.print(s + ":" + map.get(s)); } // one line lambda map.forEach((k, v) -> System.out.print(k + ":" + v));
- 說明Java8的Stream
- Collection提供了stream()方法,可以對集合做一些過濾和基本運算,而且這個當然也是有經過效能優化過的。除了stream()方法外還有parallelStream()方法,可以讓Collection各別針對它的entry另開出一個Thread,進行stream提供的運算,讓多核心的CPU資源更能有效的被利用。
List list = new ArrayList(); list.add("1"); list.add("2"); list.add("3"); list.add("5"); list.add("4"); list.stream().filter(s -> Integer.valueOf(s) < 3).forEach(s -> System.out.print(s));
- StringBuffer跟StringBuilder的比較
- StringBuffer很早就出現,只要是改善String immutable的問題(用”+”串接字串其實每次都會生出一個全新的String Object),它是synchronized的
- StringBuilder在java 1.5以後出現,最大的不同是他並非synchronized,不能在multi-threads使用,但相對來說它的速度比StringBuffer要快
- Memory Leak是甚麼,要如何避免?
- 當物件A參照物件B時,且A物件的存活時間比B要長,若B已經不使用了,它依然會占用記憶體無法被GC,當然B參照的物件也全部都會被保存,這樣的依存狀況很多的話系統記憶體會很快會消耗殆盡造成程式錯誤。
- 要避免Memory Leak可以注意以下幾點:
- 特別注意Collection(Hash、List等),尤其是被宣告為static的物件,因為他們的生命週期跟application相同
- event listener及callback函數也常常造成memory leak,event listener不用要馬上關掉它
- 若物件的成員變數有指向其他的物件,記得不用的時候把它設定為null