Java基本要點

1.什麼是Java虛擬機?爲什麼Java被稱作是“平臺無關的編程語言”?

虛擬機是一種抽象的計算機,通過在實際的計算機上方針模擬計算機的各種功能來實現的。
Java虛擬機有字節完善的硬件結構,如:處理器,堆棧,寄存器等,還有相應的指令系統。JVM屏蔽了與具體操作系統平臺相關的信息,使得Java程序只需生成在Java虛擬機上運行的字節碼就可以跨平臺使用。

java的跨平臺不是java源程序的跨平臺 ,如果是這樣,那麼所以語言都是跨平臺的, java源程序先經過javac編譯器編譯成二進制的.class字節碼文件(java的跨平臺指的就是.class字節碼文件的跨平臺,.class字節碼文件是與平臺無關的),.class文件再運行在jvm上,java解釋器(jvm的一部分)會將其解釋成對應平臺的機器碼執行,所以java所謂的跨平臺就是在不同平臺上安裝了不同的jvm,而在不同平臺上生成的.class文件都是一樣的,而.class文件再由對應平臺的jvm解釋成對應平臺的機器碼執行。 最後解釋下機器碼和字節碼的區別: 一,機器碼,完全依附硬件而存在~並且不同硬件由於內嵌指令集不同,即使相同的0 1代碼 意思也可能是不同的~換句話說,根本不存在跨平臺性~比如~不同型號的CPU,你給他個指令10001101,他們可能會解析爲不同的結果~ 二,我們知道JAVA是跨平臺的,爲什麼呢?因爲他有一個jvm,不論哪種硬件,只要你裝有jvm,那麼他就認識這個JAVA字節碼~~~~至於底層的機器碼,咱不用管,有jvm搞定,他會把字節碼再翻譯成所在機器認識的機器碼~~~

2.JDK和JRE的區別是什麼

JRE: Java Runtime Environment
JDK:Java Development Kit
JRE顧名思義是java運行時環境,包含了java虛擬機,java基礎類庫。是使用java語言編寫的程序運行所需要的軟件環境,是提供給想運行java程序的用戶使用的。
JDK顧名思義是java開發工具包,是程序員使用java語言編寫java程序所需的開發工具包,是提供給程序員使用的。JDK包含了JRE,同時還包含了編譯java源碼的編譯器javac,還包含了很多java程序調試和分析的工具:jconsole,jvisualvm等工具軟件,還包含了java程序編寫所需的文檔和demo例子程序。
如果你需要運行java程序,只需安裝JRE就可以了。如果你需要編寫java程序,需要安裝JDK。
JRE根據不同操作系統(如:windows,linux等)和不同JRE提供商(IBM,ORACLE等)有很多版本

3.什麼是值傳遞和引用傳遞?

值傳遞是對基本型變量而言的,傳遞的是該變量的一個副本,改變副本不影響原變量.
引用傳遞一般是對於對象型變量而言的,傳遞的是該對象地址的一個副本, 並不是原對象本身 。
一般認爲,java內的基礎類型數據傳遞都是值傳遞. java中實例對象的傳遞是引用傳遞

4.進程和線程的區別是什麼?

進程是執行着的應用程序,而線程是進程內部的一個執行序列。一個進程可以有多個線程。線程又叫做輕量級進程。
線程與進程的區別歸納:

a.地址空間和其它資源:進程間相互獨立,同一進程的各線程間共享。某進程內的線程在其它進程不可見。

b.通信:進程間通信IPC ,線程間可以直接讀寫進程數據段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。

c.調度和切換:線程上下文切換比進程上下文切換要快得多。

d.在多線程OS中,進程不是一個可執行的實體。

5.創建線程有幾種不同的方式

①繼承Thread類(真正意義上的線程類),是Runnable接口的實現。

②實現Runnable接口,並重寫裏面的run方法。

③使用Executor框架創建線程池。Executor框架是juc裏提供的線程池的實現。

調用線程的start():啓動此線程;調用相應的run()方法

繼承於Thread類的線程類,可以直接調用start方法啓動線程(使用static也可以實現資源共享).一個線程(對象)只能夠執行一次start(),而且不能通過Thread實現類對象的run()去啓動一個線程。

實現Runnable接口的類需要再次用Thread類包裝後才能調用start方法。(三個Thread對象包裝一個類對象,就實現了資源共享)。

線程的使用的話,注意鎖和同步的使用。(多線程訪問共享資源容易出現線程安全問題)

實現Runnable接口這種方式更受歡迎,因爲這不需要繼承Thread類。在應用設計中已經繼承了別的對象的情況下,這需要多繼承(而Java不支持多繼承),只能實現接口。同時,線程池也是非常高效的,很容易實現和使用。

6.同步方法和同步代碼塊的區別是什麼?

java允許多線程併發控制,當多個線程同時操作一個可共享的資源變量時(增刪改查),將會導致數據的不準確,相互之間產生衝突。類似於在atm取錢,銀行數據確沒有變,這是不行的,要存在於一個事務中。因此加入了同步鎖,以避免在該線程沒有結束前,調用其他線程。從而保證了變量的唯一性,準確性。
1.同步方法:
即有synchronized (同步,美 ['sɪŋkrənaɪzd] ) 修飾符修飾的方法。
由於java的每個對象都有一個內置鎖,當用此關鍵字修飾方法時,內置鎖會保護整個方法。在調用給方法前,要獲取內置鎖,否則處於阻塞狀態。
例:public synchronized getMoney(){}
注:synchronized修飾靜態方法,如果調用該靜態方法,將鎖住整個類。

2.同步代碼塊
即有synchronized修飾符修飾的語句塊,被該關鍵詞修飾的語句塊,將加上內置鎖。實現同步。
例:synchronized(Object o ){}

同步是高開銷的操作,因此儘量減少同步的內容。通常沒有必要同步整個方法,同步部分代碼塊即可。
同步方法默認用this或者當前類class對象作爲鎖。
同步代碼塊可以選擇以什麼來加鎖,比同步方法要更顆粒化,我們可以選擇只同步會發生問題的部分代碼而不是整個方法。

7.什麼是死鎖(deadlock)?

死鎖 :是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去

(1) 因爲系統資源不足。
(2) 進程運行推進順序不合適。
(3) 資源分配不當等。
如果系統資源充足,進程的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。其次,進程運行推進順序與速度不同,也可能產生死鎖。
(1) 互斥條件:一個資源每次只能被一個進程使用。
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。
死鎖的解除與預防:
理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和解除死鎖。所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確定資源的合理分配算法,避免進程永久佔據系統資源。此外,也要防止進程在處於等待狀態的情況下佔用資源。因此,對資源的分配要給予合理的規劃。
一種非常簡單的避免死鎖的方式就是:指定獲取鎖的順序,並強制線程按照指定的順序獲取鎖。因此,如果所有的線程都是以同樣的順序加鎖和釋放鎖,就不會出現死鎖了。

8.Java集合類框架的基本接口有哪些?

總共有兩大接口:Collection 和Map ,一個元素集合,一個是鍵值對集合; 其中List和Set接口繼承了Collection接口,一個是有序元素集合,一個是無序元素集合; 而ArrayList和 LinkedList 實現了List接口,HashSet實現了Set接口,這幾個都比較常用; HashMap 和HashTable實現了Map接口,並且HashTable是線程安全的,但是HashMap性能更好;
在這裏插入圖片描述

9.Java中的HashMap的工作原理是什麼

Java中的HashMap是以鍵值對(key-value)的形式存儲元素的。HashMap需要一個hash函數,它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素。當調用put()方法的時候,HashMap會計算key的hash值,然後把鍵值對存儲在集合中合適的索引上。如果key已經存在了,value會被更新成新值。HashMap的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。
https://blog.csdn.net/vking_wang/article/details/14166593
Java8系列之重新認識HashMap

10.hashCode()和equals()方法的重要性體現在什麼地方?

通過hashCode和equals方法保證元素的唯一性,當重寫equals方法時,必須重寫hashCode方法,因爲如果不重寫這兩個方法,就會默認使用Object的方法,一般是不相同的,所以就會導致存儲了重複值,與hashset、hashmap等性質衝突。
哈希表判斷通過hashCode和equals方法判斷元素是否相同的步驟如下所示:
先看hashCode的值是否相同,因爲這個是邏輯內存地址,
如果不相同:則表示對象不相同
如果相同:繼續在桶結構中執行equals方法,equals方法返回
True:表示對象相同,
Fasle:表示對象不相同
只有hashCode和equals方法都返回true,才表示對象相同

equals()與‘==’的區別:**默認情況下也就是從超類Object繼承而來的equals方法與‘==’是完全等價的,比較的都是對象的內存地址,但我們可以重寫equals方法,使其按照我們的需求的方式進行比較,如String類重寫了equals方法,使其比較的是字符的序列,而不再是內存地址。

11.HashMap和Hashtable有什麼區別?

HashMap和Hashtable都實現了Map接口,因此很多特性非常相似。
1、HashMap是非線程安全的,HashTable是線程安全的。
2、HashMap的鍵和值都允許有null值存在,而HashTable則不行。
3、因爲線程安全的問題,HashMap效率比HashTable的要高。
4、Hashtable是同步的,而HashMap不是。因此,HashMap更適合於單線程環境,而Hashtable適合於多線程環境。

一般現在不建議用HashTable, ①是HashTable是遺留類,內部實現很多沒優化和冗餘。②即使在多線程環境下,現在也有同步的ConcurrentHashMap替代,沒有必要因爲是多線程而用HashTable。

12.Java集合類框架的最佳實踐有哪些?

在這裏插入圖片描述

13.Java中垃圾回收有什麼目的?什麼時候進行垃圾回收?

垃圾回收是在內存中存在沒有引用的對象或超過作用域的對象時進行。
垃圾回收的目的是識別並且丟棄應用不再使用的對象來釋放和重用資源。釋放堆中不需要保存的對象,達到內存的充分利用。
1.回收哪些對象的判定

垃圾回收最簡單的思路是採用引用計數的方式,即記錄對象被引用的次數,直到一段時間內對象都沒有被其他對象引用,此時可以確定該對象能被回收,引用計數實現簡單,運行高效,但是有一個循環引用的問題,即兩個本應被回收的對象因爲互相引用而無法被回收,針對這個問題又有了弱引用,即把兩個互相引用的一個引用計數改爲弱引用,弱引用不會使次數加1,c++即是這麼做的。

2.如何回收
jvm有兩種回收方式,一種是標記完待回收的對象之後一起釋放內存,這種方法的缺點是會產生較多難以重複利用的內存碎片。另一種爲了避免內存碎片的出現,將內存分爲兩塊,一塊使用,一塊不使用,標記完所有待回收的對象之後,將還要使用的內存複製到不使用的區域,然後對使用的整體區域進行內存回收,這種方法沒有內存碎片問題,但是每次回收的複製工作很耗性能。
通過統計發現,在內存中存活越久的對象就越不容易被回收,越是新分配的內存對象就越可能會被回收。根據這個特性,把內存區域分爲新生代和老年代(有的虛擬機會分爲很多代),新生代容易被回收,採用複製內存再回收的方法,老年代不容易被回收,採用標記後回收和複製內存相結合的方法。
3.什麼時候回收
程序員可以手動調用gc,一般是系統等到新生代的內存區佔滿了又需要分配內存的時候,這個時候新生代就變成了老年代,等老年代的內存佔滿之後開始回收老年代所佔的內存區。
在Java中,對象什麼時候可以被垃圾回收?
當一個對象到GC Roots不可達時,在下一個垃圾回收週期中嘗試回收該對象,如果該對象重寫了finalize()方法,並在這個方法中成功自救(將自身賦予某個引用),那麼這個對象不會被回收。但如果這個對象沒有重寫finalize()方法或者已經執行過這個方法,也自救失敗,該對象將會被回收。

14.如果對象的引用被置爲null,垃圾收集器是否會立即釋放對象佔用的內存?

不會立即釋放對象佔用的內存。 如果對象的引用被置爲null,只是斷開了當前線程棧幀中對該對象的引用關係,而垃圾收集器是運行在後臺的線程,只有當用戶線程運行到安全點(safe point)或者安全區域纔會掃描對象引用關係,掃描到對象沒有被引用則會標記對象,這時候仍然不會立即釋放該對象內存,因爲有些對象是可恢復的(在 finalize方法中恢復引用 )。只有確定了對象無法恢復引用的時候纔會清除對象內存。在下一個垃圾回收週期中,這個對象將是可被回收的

未完待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章