面試題一Java基礎
-
String s = new String(“xyz”);創建了1幾個對象
兩個,一個字符串對象,一個字符對象引用對象
-
Overload和Override的區別?Overloaded的方法是否可以改變返回值的類型?
方法的重寫Overrideing和重載Overloading是Java多態性的不同表現。重寫Overrideing是父類與子類之間多態性的一種表現,重載Overloing是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫Overrideing。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱爲方法的重載Overloading。
Overloaded的方法是可以改變返回值的類型。
-
最常見的Runtime Exception
NullPointerException 空指針引用異常
ClassCastException 類型轉換異常
IndexOutOfBoundsException 下標越界異常
NumberFormatException 數字格式異常
EOFException 文件已結束異常
FiileNotFoundException 文件未找到異常
NoSuchMethodException 方法未找到異常
-
error和exception有什麼區別?
error表示恢復不是不可能但很困難的情況下的1一種嚴重問題,比如內存溢出,不可能指望程序能處理這樣的情況;
exception表示一種設計或實現問題,也就是說,它表示如果程序運行正常,從不會發生的情況
-
String、StringBuffer和StringBuilder的區別?
String的值是不可變的,這就導致每次對String的操作都會生成新的String對象,這樣不僅效率低下,而且大量浪費有限的內存空間。
StringBuffer 和 StringBuilder 的值是長度可變的,並且不產生新的未使用對象。StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在於 StringBuilder 的方法不是線程安全的(不能同步訪問)。
String可以賦空值,後者不可以。
-
線程和進程的區別?
進程是操作系統資源分配的基本單位,而線程是任務調度和執行的基本單位。
-
簡單介紹一下集合?
集合主要分爲兩大類:Collection和Map
Collection: ├List:有序可重複 ├ArrayList 底層數據結構:數組 查詢快,增刪慢 線程不安全,效率高 ├LinkedList 底層數據結構:鏈表 查詢慢,增刪快 線程不安全,效率高 ├Vector 底層數據結構:數組 查詢快,增刪慢 線程安全,效率低 ├Set:無序不可重複 ├HashSet 底層數據結構:哈希表 如何保證元素的唯一性呢? 依賴兩個方法:hashCode()和equals(),自動生成即可 ├LinkedHashSet 底層數據結構:鏈表和哈希表 由鏈表保證元素有序 由哈希表保證元素唯一 ├TreeSet 底層數據結構:紅黑樹 Map: |-HashMap: 底層數據結構:鍵是哈希表結構,保證鍵的唯一性。可以存入null鍵,null值 線程不安全,效率高。 允許key或者value爲null |-Hashtable: 底層數據結構:哈希表,不可以存入null鍵,null值 線程是安全,效率低。 |-TreeMap: 底層數據結構:二叉樹,保證鍵的排序和唯一性。需要使用Comparable或者Comparator 進行比較排序 線程不安全,效率高。
-
Hashmap線程不安全,怎麼實現一個線程安全的HashMap?
我們知道HashMap底層的數據結構是數組+鏈表/紅黑樹,默認初始容量是16,當數組中的元素大於hashMap的初始容量乘以加載因子時(加載因子默認是0.75),HashMap就會進行擴容,容量變爲原來的2倍,然後將原來的數據重新映射到新的桶裏面,然後將原來的桶逐個置爲null,使得引用失效。也就是在hashMap進行擴容的時候容易發生HashMap線程不安全。HashMap線程不安全主要會產生以下兩種情況:1、在多線程的環境下,進行put()的時候會導致多線程的數據不一致。2、在多線程的環境下,對HashMap進行get操作可能因爲擴容而引起死循環。
實現一個線程安全的HashMap
1、使用ConcurrentHashMap
2、使用Collections.synchonizedMap(Map<K,v> m)方法將HashMap變成一個線程安全的map。
-
線程的生命週期?
A:新生 new,每個線程都有自己的運行空間
B:就緒 start(),就緒不代表運行,代表線程具有可運行的能力,在就緒隊列中排隊等待cpu調度
C:運行 cpu把時間片分配給某個線程,這個線程就就行運行狀態
D:阻塞 sleep()…
E:死亡 執行完畢 -
start()方法和run()方法的區別?
只有調用start()方法,纔會表現出多線程的特徵,不同線程的run()方法裏面的代碼交替執行。如果只是調用run()方法,那麼代碼還是同步執行的,必須等待一個線程的run()方法裏面的代碼全部執行完畢之後,另外一個線程纔可以執行其run()方法裏面的代碼。
-
java中的notify和notifyAll有什麼區別?
這又是一個刁鑽的問題,因爲多線程可以等待單監控鎖,Java API 的設計人員提供了一些方法當等待條件改變的時候通知它們,但是這些方法沒有完全實現。notify()方法不能喚醒某個具體的線程,所以只有一個線程在等 待的時候它纔有用武之地。而notifyAll()喚醒所有線程並允許他們爭奪鎖確保了至少有一個線程能繼續運行。
-
什麼是線程池?爲什麼要使用它?
創建線程花費昂貴的資源和時間,如果任務來了才創建那麼響應時間會變長,而且一個進程能夠創建的線程數有限。爲了避免這些問題,在程序啓動的時候就創建若干線程來響應處理,它們被稱爲線程池,裏面的線程叫工作線程。
-
如何避免死鎖?
死鎖是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。這是一個嚴重的問題,因爲死鎖會讓你的程序掛起無法完成任務,死鎖的發生必須滿足以下四個條件:- 互斥條件:一個資源每次只能被一個進程使用。
- 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
- 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
- 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。
避免死鎖最簡單的方法就是阻止循環等待條件,將系統中所有的資源設置標誌位、排序,規定所有的進程申請資源必須以一定的順序(升序或降序)做操作來避免死鎖。