基本數據類型的比較的值相等.類的比較的內存的地址,便是否是同一個對象,在不覆蓋equals的狀況下,同比較內存地址,原實現也爲 == ,如String等重寫了equals方法.hashCode也是Object類的一個方法。返回一個離散的int型整數。在集合類操做中使用,爲了提升查詢速度。(HashMap,HashSet等比較是否爲同一個)若是兩個對象equals,Java運行時環境會認爲他們的hashcode必定相等。若是兩個對象不equals,他們的hashcode有可能相等。若是兩個對象hashcode相等,他們不必定equals。若是兩個對象hashcode不相等,他們必定不equals。java
int 基本類型integer 對象 int的封裝類程序員
String:字符串常量 不適用於常常要改變值得狀況,每次改變至關於生成一個新的對象StringBuffer:字符串變量 (線程安全)StringBuilder:字符串變量(線程不安全) 確保單線程下可用,效率略高於StringBuffer面試
內部類的做用內部類可直接訪問外部類的屬性Java中內部類主要分爲成員內部類、局部內部類(嵌套在方法和做用域內)、匿名內部類(沒構造方法)、靜態內部類(static修飾的類,不能使用任何外圍類的非static成員變量和方法, 不依賴外圍類)算法
進程是cpu資源分配的最小單位,線程是cpu調度的最小單位。進程之間不能共享資源,而線程共享所在進程的地址空間和其它資源。一個進程內可擁有多個線程,進程可開啓進程,也可開啓線程。一個線程只能屬於一個進程,線程可直接使用同進程的資源,線程依賴於進程而存在。數組
final:修飾類、成員變量和成員方法,類不可被繼承,成員變量不可變,成員方法不可重寫finally:與try…catch…共同使用,確保不管是否出現異常都能被調用到finalize:類的方法,垃圾回收以前會調用此方法,子類能夠重寫finalize()方法實現對資源的回收緩存
Serializable Java 序列化接口 在硬盤上讀寫 讀寫過程當中有大量臨時變量的生成,內部執行大量的i/o操做,效率很低。Parcelable Android 序列化接口 效率高 使用麻煩 在內存中讀寫(AS有相關插件 一鍵生成所需方法) ,對象不能保存到磁盤中安全
可繼承 不可重寫 而是被隱藏若是子類裏面定義了靜態方法和屬性,那麼這時候父類的靜態方法或屬性稱之爲"隱藏"。若是你想要調用父類的靜態方法和屬性,直接經過父類名.方法或變量名完成。網絡
java中內部類主要分爲成員內部類、局部內部類(嵌套在方法和做用域內)、匿名內部類(沒構造方法)、靜態內部類(static修飾的類,不能使用任何外圍類的非static成員變量和方法, 不依賴外圍類)使用內部類最吸引人的緣由是:每一個內部類都能獨立地繼承一個(接口的)實現,因此不管外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。由於Java不支持多繼承,支持實現多個接口。但有時候會存在一些使用接口很難解決的問題,這個時候咱們能夠利用內部類提供的、能夠繼承多個具體的或者抽象的類的能力來解決這些程序設計問題。能夠這樣說,接口只是解決了部分問題,而內部類使得多重繼承的解決方案變得更加完整。數據結構
integer Intrger.parseInt(string);
Integerstring Integer.toString();多線程
1.全部實例都沒有活動線程訪問。
2.沒有被其餘任何實例訪問的循環引用實例。
3.Java 中有不一樣的引用類型。判斷實例是否符合垃圾收集的條件都依賴於它的引用類型。要判斷怎樣的對象是沒用的對象。這裏有2種方法:1.採用標記計數的方法:給內存中的對象給打上標記,對象被引用一次,計數就加1,引用被釋放了,計數就減一,當這個計數爲0的時候,這個對象就能夠被回收了。固然,這也就引起了一個問題:循環引用的對象是沒法被識別出來而且被回收的。因此就有了第二種方法:2.採用根搜索算法:從一個根出發,搜索全部的可達對象,這樣剩下的那些對象就是須要被回收的
靜態代理類:由程序員建立或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。動態代理類:在程序運行時,運用反射機制動態建立而成。
答:方法的重寫Overriding和重載Overloading是Java多態性的不一樣表現重寫Overriding是父類與子類之間多態性的一種表現重載Overloading是一個類中多態性的一種表現.
JAVA反射機制是在運行狀態中, 對於任意一個類, 都可以知道這個類的全部屬性和方法; 對於任意一個對象, 都可以調用它的任意一個方法和屬性。 從對象出發,經過反射(Class類)能夠取得取得類的完整信息(類名 Class類型,所在包、具備的全部方法 Method[]類型、某個方法的完整信息(包括修飾符、返回值類型、異常、參數類型)、全部屬性 Field[]、某個屬性的完整信息、構造器 Constructors),調用類的屬性或方法本身的總結: 在運行過程當中得到類、對象、方法的全部信息。
元註解元註解的做用就是負責註解其餘註解。java5.0的時候,定義了4個標準的meta-annotation類型,它們用來提供對其餘註解的類型做說明。
1.@Target
2.@Retention
3.@Documented
4.@Inherited
在源碼中string是用final 進行修飾,它是不可更改,不可繼承的常量。
一、字符串池的需求字符串池是方法區(Method Area)中的一塊特殊的存儲區域。當一個字符串已經被建立而且該字符串在 池 中,該字符串的引用會當即返回給變量,而不是從新建立一個字符串再將引用返回給變量。若是字符串不是不可變的,那麼改變一個引用(如: string2)的字符串將會致使另外一個引用(如: string1)出現髒數據。
二、容許字符串緩存哈希碼在java中經常會用到字符串的哈希碼,例如: HashMap 。String的不變性保證哈希碼始終一,所以,他能夠不用擔憂變化的出現。 這種方法意味着沒必要每次使用時都從新計算一次哈希碼——這樣,效率會高不少。
三、安全String普遍的用於java 類中的參數,如:網絡鏈接(Network connetion),打開文件(opening files )等等。若是String不是不可變的,網絡鏈接、文件將會被改變——這將會致使一系列的安全威脅。操做的方法本覺得鏈接上了一臺機器,但實際上卻不是。因爲反射中的參數都是字符串,一樣,也會引發一系列的安全問題。
首先equals與hashcode間的關係是這樣的:
一、若是兩個對象相同(即用equals比較返回true),那麼它們的hashCode值必定要相同;
二、若是兩個對象的hashCode相同,它們並不必定相同(即用equals比較返回false)因爲爲了提升程序的效率才實現了hashcode方法,先進行hashcode的比較,若是不一樣,那沒就沒必要在進行equals的比較了,這樣就大大減小了equals比較的次數,這對比須要比較的數量很大的效率提升是很明顯的
1)Set是最簡單的一種集合。集合中的對象不按特定的方式排序,而且沒有重複對象。 Set接口主要實現了兩個實現類:
HashSet: HashSet類按照哈希算法來存取集合中的對象,存取速度比較快TreeSet :TreeSet類實現了SortedSet接口,可以對集合中的對象進行排序。
2)List的特徵是其元素以線性方式存儲,集合中能夠存放重複對象。
ArrayList() : 表明長度能夠改變得數組。能夠對元素進行隨機的訪問,向ArrayList()中插入與刪除元素的速度慢。
LinkedList(): 在實現中採用鏈表數據結構。插入和刪除速度快,訪問速度慢。
3)Map 是一種把鍵對象和值對象映射的集合,它的每個元素都包含一對鍵對象和值對象。 Map沒有繼承於Collection接口 從Map集合中檢索元素時,只要給出鍵對象,就會返回對應的值對象。
HashMap:Map基於散列表的實現。插入和查詢「鍵值對」的開銷是固定的。能夠經過構造器設置容量capacity和負載因子load factor,以調整容器的性能。LinkedHashMap: 相似於HashMap,可是迭代遍歷它時,取得「鍵值對」的順序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一點。而在迭代訪問時發而更快,由於它使用鏈表維護內部次序。
TreeMap : 基於紅黑樹數據結構的實現。查看「鍵」或「鍵值對」時,它們會被排序(次序由Comparabel或Comparator決定)。TreeMap的特色在 於,你獲得的結果是通過排序的。TreeMap是惟一的帶有subMap()方法的Map,它能夠返回一個子樹。
WeakHashMap :弱鍵(weak key)Map,Map中使用的對象也被容許釋放: 這是爲解決特殊問題設計的。若是沒有map以外的引用指向某個「鍵」,則此「鍵」能夠被垃圾收集器回收。
一、存儲方式不一樣HashMap內部有一個HashMapEntry<K, V>[]對象,每個鍵值對都存儲在這個對象裏,當使用put方法添加鍵值對時,就會new一個HashMapEntry對象,二、添加數據時擴容時的處理不同,進行了new操做,從新建立對象,開銷很大。ArrayMap用的是copy數據,因此效率相對要高。三、ArrayMap提供了數組收縮的功能,在clear或remove後,會從新收縮數組,收縮空間四、ArrayMap採用二分法查找;
1 HashMap不是線程安全的,效率高一點、方法不是Synchronize的要提供外同步,有containsvalue和containsKey方法。hashtable是,線程安全,不容許有null的鍵和值,效率稍低,方法是是Synchronize的。有contains方法方法。Hashtable 繼承於Dictionary 類
hashMap:HashMap實現了Map接口,HashMap儲存鍵值對,使用put()方法將元素放入map中,HashMap中使用鍵對象來計算hashcode值,HashMap比較快,由於是使用惟一的鍵來獲取對象。HashSet實現了Set接口,HashSet僅僅存儲對象,使用add()方法將元素放入set中,HashSet使用成員對象來計算hashcode值,對於兩個對象來講hashcode可能相同,因此equals()方法用來判斷對象的相等性,若是兩個對象不一樣的話,那麼返回false。HashSet較HashMap來講比較慢。
HashSet不能添加劇復的元素,當調用add(Object)方法時候,首先會調用Object的hashCode方法判hashCode是否已經存在,如不存在則直接插入元素;若是已存在則調用Object對象的equals方法判斷是否返回true,若是爲true則說明元素已經存在,如爲false則插入元素。
ArrayList是基於數組實現的,ArrayList線程不安全。LinkedList是基於雙鏈表實現的:使用場景:(1)若是應用程序對各個索引位置的元素進行大量的存取或刪除操做,ArrayList對象要遠優於LinkedList對象;( 2 ) 若是應用程序主要是對列表進行循環,而且循環時候進行插入或者刪除操做,LinkedList對象要遠優於ArrayList對象;
數組是將元素在內存中連續存儲的;它的優勢:由於數據是連續存儲的,內存地址連續,因此在查找數據的時候效率比較高;它的缺點:在存儲以前,咱們須要申請一塊連續的內存空間,而且在編譯的時候就必須肯定好它的空間的大小。在運行的時候空間的大小是沒法隨着你的須要進行增長和減小而改變的,當數據兩比較大的時候,有可能會出現越界的狀況,數據比較小的時候,又有可能會浪費掉內存空間。在改變數據個數時,增長、插入、刪除數據效率比較低。
鏈表:是動態申請內存空間,不須要像數組須要提早申請好內存的大小,鏈表只需在用的時候申請就能夠,根據須要來動態申請或者刪除內存空間,對於數據增長和刪除以及插入比數組靈活。還有就是鏈表中數據在內存中能夠在任意的位置,經過應用來關聯數據(就是經過存在元素的指針來聯繫)
java有三種建立線程的方式,分別是繼承Thread類、實現Runable接口和使用線程池
線程是進程的子集,一個進程能夠有不少線程,每條線程並行執行不一樣的任務。不一樣的進程使用不一樣的內存空間,而全部的線程共享一片相同的內存空間。別把它和棧內存搞混,每一個線程都擁有單獨的棧內存用來存儲本地數據。
但仍是能今後區分出面試者對Java線程模型的理解程度。start()方法被用來啓動新建立的線程,並且start()內部調用了run()方法,這和直接調用run()方法的效果不同。當你調用run()方法的時候,只會是在原來的線程中調用,沒有新的線程啓動,start()方法纔會啓動新線程。
static Semaphore sSemaphore = new Semaphore(6) 表示該方法最多容許幾個線程訪問
semaphore.availablePermits():能夠獲取當前容許進入方法的線程數量
semaphore.acquire() 請求一個信號量,這時候的信號量個數-1(一旦沒有可以使用的信號量,也即信號量個數變爲負數時,再次請求的時候就會阻塞,直到其餘線程釋放了信號量)
semaphore.release() 釋放一個信號量,此時信號量個數+1
;Java程序中wait 和 sleep都會形成某種形式的暫停,它們能夠知足不一樣的須要。wait()方法用於線程間通訊,若是等待條件爲真且其它線程被喚醒時它會釋放鎖,而sleep()方法僅僅釋放CPU資源或者讓當前線程中止執行一段時間,但不會釋放鎖。
等待對象的同步鎖,須要得到該對象的同步鎖才能夠調用這個方法,不然編譯能夠經過,但運行時會收到一個異常:IllegalMonitorStateException。調用任意對象的 wait() 方法致使該線程阻塞,該線程不可繼續執行,而且該對象上的鎖被釋放。喚醒在等待該對象同步鎖的線程(只喚醒一個,若是有多個在等待),注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程,並且不是按優先級。調用任意對象的notify()方法則致使因調用該對象的 wait()方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到得到鎖後才真正可執行)。
阻塞式方法是指程序會一直等待該方法完成期間不作其餘事情,ServerSocket的accept()方法就是一直等待客戶端鏈接。這裏的阻塞是指調用結果返回以前,當前線程會被掛起,直到獲得結果以後纔會返回。此外,還有異步和非阻塞式方法在任務完成前就返回。一種是調用它裏面的stop()方法另外一種就是你本身設置一箇中止線程的標記 (推薦這種)
1.synchronized;2.Object方法中的wait,notify;3.ThreadLocal機制 來實現的。
一、synchronized關鍵字修改的方法。二、synchronized關鍵字修飾的語句塊三、使用特殊域變量(volatile)實現線程同步
ListList list = Collections.synchronizedList(new ArrayList());
java的對象鎖和類鎖:java的對象鎖和類鎖在鎖的概念上基本上和內置鎖是一致的,可是,兩個鎖實際是有很大的區別的,對象鎖是用於對象實例方法,或者一個對象實例上的,類鎖是用於類的靜態方法或者一個類的class對象上的。咱們知道,類的對象實例能夠有不少個,可是每一個類只有一個class對象,因此不一樣對象實例的對象鎖是互不干擾的,可是每一個類只有一個類鎖。可是有一點必須注意的是,其實類鎖只是一個概念上的東西,並非真實存在的,它只是用來幫助咱們理解鎖定實例方法和靜態方法的區別的
1.volatile本質是在告訴jvm當前變量在寄存器(工做內存)中的值是不肯定的,須要從主存中讀取;synchronized則是鎖定當前變量,只有當前線程能夠訪問該變量,其餘線程被阻塞住。
2.volatile僅能使用在變量級別;synchronized則可使用在變量、方法、和類級別的
3.volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則能夠保證變量的修改可見性和原子性
4.volatile不會形成線程的阻塞;synchronized可能會形成線程的阻塞。
5.volatile標記的變量不會被編譯器優化;synchronized標記的變量能夠被編譯器優化
java在過去很長一段時間只能經過synchronized關鍵字來實現互斥,它有一些缺點。好比你不能擴展鎖以外的方法或者塊邊界,嘗試獲取鎖時不能中途取消等。Java 5 經過Lock接口提供了更復雜的控制來解決這些問題。 ReentrantLock 類實現了 Lock,它擁有與 synchronized 相同的併發性和內存語義且它還具備可擴展性。
死鎖產生的緣由系統資源的競爭系統資源的競爭致使系統資源不足,以及資源分配不當,致使死鎖。進程運行推動順序不合適互斥條件:一個資源每次只能被一個進程使用,即在一段時間內某 資源僅爲一個進程所佔有。此時如有其餘進程請求該資源,則請求進程只能等待。
請求與保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其餘進程佔有,此時請求進程被阻塞,但對本身已得到的資源保持不放。
不可剝奪條件:進程所得到的資源在未使用完畢以前,不能被其餘進程強行奪走,即只能 由得到該資源的進程本身來釋放(只能是主動釋放)。
循環等待條件: 若干進程間造成首尾相接循環等待資源的關係這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不知足,就不會發生死鎖。
死鎖的避免與預防:死鎖避免的基本思想:系統對進程發出每個系統可以知足的資源申請進行動態檢查,並根據檢查結果決定是否分配資源,若是分配後系統可能發生死鎖,則不予分配,不然予以分配。這是一種保證系統不進入死鎖狀態的動態策略。理解了死鎖的緣由,尤爲是產生死鎖的四個必要條件,就能夠最大可能地避免、預防和解除死鎖。因此,在系統設計、進程調度等方面注意如何讓這四個必要條件不成立,如何肯定資源的合理分配算法,避免進程永久佔據系統資源。此外,也要防止進程在處於等待狀態的狀況下佔用資源。所以,對資源的分配要給予合理的規劃。
死鎖避免和死鎖預防的區別:死鎖預防是設法至少破壞產生死鎖的四個必要條件之一,嚴格的防止死鎖的出現,而死鎖避免則不那麼嚴格的限制產生死鎖的必要條件的存在,由於即便死鎖的必要條件存在,也不必定發生死鎖。死鎖避免是在系統運行過程當中注意避免死鎖的最終發生。
建立線程要花費昂貴的資源和時間,若是任務來了才建立線程那麼響應時間會變長,並且一個進程能建立的線程數有限。爲了不這些問題,在程序啓動的時候就建立若干線程來響應處理,它們被稱爲線程池,裏面的線程叫工做線程。從JDK1.5開始,Java API提供了Executor框架讓你能夠建立不一樣的線程池。好比單線程池,每次處理一個任務;數目固定的線程池或者是緩存線程池(一個適合不少生存期短的任務的程序的可擴展線程池)。
爲何把這個問題歸類在多線程和併發面試題裏?由於棧是一塊和線程緊密相關的內存區域。每一個線程都有本身的棧內存,用於存儲本地變量,方法參數和棧調用,一個線程中存儲的變量對其它線程是不可見的。而堆是全部線程共享的一片公用內存區域。對象都在堆裏建立,爲了提高效率線程會從堆中弄一個緩存到本身的棧,若是多個線程使用該變量就可能引起問題,這時volatile 變量就能夠發揮做用了,它要求線程從主存中讀取變量的值。
在多線程中有多種方法讓線程按特定順序執行,你能夠用線程類的join()方法在一個線程中啓動另外一個線程,另一個線程完成該線程繼續執行。爲了確保三個線程的順序你應該先啓動最後一個(T3調用T2,T2調用T1),這樣T1就會先完成而T3最後完成。線程間通訊咱們知道線程是CPU調度的最小單位。在Android中主線程是不可以作耗時操做的,子線程是不可以更新UI的。而線程間通訊的方式有不少,好比廣播,Eventbus,接口回掉,在Android中主要是使用handler。handler經過調用sendmessage方法,將保存消息的Message發送到Messagequeue中,而looper對象不斷的調用loop方法,從messageueue中取出message,交給handler處理,從而完成線程間通訊。