1. 面向對象和麪向過程的區別java
優勢: 性能比面向對象高,由於類調用時須要實例化,開銷比較大,比較消耗資源;好比單片機、嵌入式開發、Linux/Unix等通常採用面向過程開發,性能是最重要的因素。程序員
缺點: 沒有面向對象易維護、易複用、易擴展面試
優勢: 易維護、易複用、易擴展,因爲面向對象有封裝、繼承、多態性的特性,能夠設計出低耦合的系統,使系統更加靈活、更加易於維護編程
缺點: 性能比面向過程低小程序
這幾個是Java中很基本很基本的東西,可是我相信必定還有不少人搞不清楚!爲何呢?由於咱們大多數時候在使用現成的編譯工具以及環境的時候,並無去考慮這些東西。數組
JDK: 顧名思義它是給開發者提供的開發工具箱,是給程序開發者用的。它除了包括完整的JRE(Java Runtime Environment),Java運行環境,還包含了其餘供開發者使用的工具包。瀏覽器
JRE: 普通用戶而只須要安裝JRE(Java Runtime Environment)來運行Java程序。而程序開發者必須安裝JDK來編譯、調試程序。安全
JVM: 當咱們運行一個程序時,JVM負責將字節碼轉換爲特定機器代碼,JVM提供了內存管理/垃圾回收和安全機制等。這種獨立於硬件和操做系統,正是java程序能夠一次編寫多處執行的緣由。網絡
區別與聯繫:多線程
Java中引入了虛擬機的概念,即在機器和編譯程序之間加入了一層抽象的虛擬的機器。這臺虛擬的機器在任何平臺上都提供給編譯程序一個的共同的接口。
編譯程序只須要面向虛擬機,生成虛擬機可以理解的代碼,而後由解釋器來將虛擬機代碼轉換爲特定系統的機器碼執行。在Java中,這種供虛擬機理解的代碼叫作 字節碼(即擴展名爲 .class的文件),它不面向任何特定的處理器,只面向虛擬機。
每一種平臺的解釋器是不一樣的,可是實現的虛擬機是相同的。Java源程序通過編譯器編譯後變成字節碼,字節碼由虛擬機解釋執行,虛擬機將每一條要執行的字節碼送給解釋器,解釋器將其翻譯成特定機器上的機器碼,而後在特定的機器上運行。這也就是解釋了Java的編譯與解釋並存的特色。
Java源代碼---->編譯器---->jvm可執行的Java字節碼(即虛擬指令)---->jvm---->jvm中解釋器----->機器可執行的二進制機器碼---->程序運行。
Java語言經過字節碼的方式,在必定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特色。因此Java程序運行時比較高效,並且,因爲字節碼並不專對一種特定的機器,所以,Java程序無須從新編譯即可在多種不一樣的計算機上運行。
我知道不少人沒學過C++,可是面試官就是沒事喜歡拿我們Java和C++比呀!沒辦法!!!就算沒學過C++,也要記下來!
一個程序中能夠有多個類,但只能有一個類是主類。在Java應用程序中,這個主類是指包含main()方法的類。而在Java小程序中,這個主類是一個繼承自系統類JApplet或Applet的子類。應用程序的主類不必定要求是public類,但小程序的主類要求必須是public類。主類是Java程序執行的入口點。
簡單說應用程序是從主線程啓動(也就是main()方法)。applet小程序沒有main方法,主要是嵌在瀏覽器頁面上運行(調用init()線程或者run()來啓動),嵌入瀏覽器這點跟flash的小遊戲相似。
在講繼承的時候咱們就知道父類的私有屬性和構造方法並不能被繼承,因此Constructor也就不能被override,可是能夠overload,因此你能夠看到一個類中有多個構造函數的狀況。
重載: 發生在同一個類中,方法名必須相同,參數類型不一樣、個數不一樣、順序不一樣,方法返回值和訪問修飾符能夠不一樣,發生在編譯時。
重寫: 發生在父子類中,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類;若是父類方法訪問修飾符爲private則子類就不能重寫該方法。
封裝把一個對象的屬性私有化,同時提供一些能夠被外界訪問的屬性的方法,若是不想被外界方法,咱們大可沒必要提供方法給外界訪問。可是若是一個類沒有提供給外界訪問的方法,那麼這個類也沒有什麼意義了。
繼承是使用已存在的類的定義做爲基礎創建新類的技術,新類的定義能夠增長新的數據或新的功能,也能夠用父類的功能,但不能選擇性地繼承父類。經過使用繼承咱們可以很是方便地複用之前的代碼。
關於繼承以下3點請記住:
所謂多態就是指程序中定義的引用變量所指向的具體類型和經過該引用變量發出的方法調用在編程時並不肯定,而是在程序運行期間才肯定,即一個引用變量倒底會指向哪一個類的實例對象,該引用變量發出的方法調用究竟是哪一個類中實現的方法,必須在由程序運行期間才能決定。
在Java中有兩種形式能夠實現多態:繼承(多個子類對同一方法的重寫)和接口(實現接口並覆蓋接口中同一方法)。
可變性
String類中使用字符數組保存字符串,private final char value[],因此string對象是不可變的。StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,char[]value,這兩種對象都是可變的。
線程安全性
String中的對象是不可變的,也就能夠理解爲常量,線程安全。AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操做,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,因此是線程安全的。StringBuilder並無對方法進行加同步鎖,因此是非線程安全的。
性能
每次對String 類型進行改變的時候,都會生成一個新的String對象,而後將指針指向新的String 對象。StringBuffer每次都會對StringBuffer對象自己進行操做,而不是生成新的對象並改變對象引用。相同狀況下使用StirngBuilder 相比使用StringBuffer 僅能得到10%~15% 左右的性能提高,但卻要冒多線程不安全的風險。
對於三者使用的總結:
若是要操做少許的數據用 = String 單線程操做字符串緩衝區 下操做大量數據 = StringBuilder 多線程操做字符串緩衝區 下操做大量數據 = StringBuffer
裝箱:將基本類型用它們對應的引用類型包裝起來;
拆箱:將包裝類型轉換爲基本數據類型;
因爲靜態方法能夠不經過對象進行調用,所以在靜態方法裏,不能調用其餘非靜態變量,也不能夠訪問非靜態變量成員。
Java程序在執行子類的構造方法以前,若是沒有用super()來調用父類特定的構造方法,則會調用父類中「沒有參數的構造方法」。所以,若是父類中只定義了有參數的構造方法,而在子類的構造方法中又沒有用super()來調用父類中特定的構造方法,則編譯時將發生錯誤,由於Java程序在父類中找不到沒有參數的構造方法可供執行。解決辦法是在父類里加上一個不作事且沒有參數的構造方法。
剛開始的時候JavaAPI所必需的包是java開頭的包,javax當時只是擴展API包來講使用。然而隨着時間的推移,javax逐漸的擴展成爲Java API的組成部分。可是,將擴展從javax包移動到java包將是太麻煩了,最終會破壞一堆現有的代碼。所以,最終決定javax包將成爲標準API的一部分。
因此,實際上java和javax沒有區別。這都是一個名字。
new運算符,new建立對象實例(對象實例在堆內存中),對象引用指向對象實例(對象引用存放在棧內存中)。一個對象引用能夠指向0個或1個對象(一根繩子能夠不繫氣球,也能夠系一個氣球);一個對象能夠有n個引用指向它(能夠用n條繩子繫住一個氣球)。
方法的返回值是指咱們獲取到的某個方法體中的代碼執行後產生的結果!(前提是該方法可能產生結果)。返回值的做用:接收出結果,使得它能夠用於其餘的操做!
主要做用是完成對類對象的初始化工做。能夠執行。由於一個類即便沒有聲明構造方法也會有默認的不帶參數的構造方法。
對象的相等 比的是內存中存放的內容是否相等而引用相等 比較的是他們指向的內存地址是否相等。
幫助子類作初始化工做。
== : 它的做用是判斷兩個對象的地址是否是相等。即,判斷兩個對象是否是同一個對象。(基本數據類型==比較的是值,引用數據類型==比較的是內存地址)
equals() : 它的做用也是判斷兩個對象是否相等。但它通常有兩種使用狀況:
舉個例子:
說明:
面試官可能會問你:「你重寫過 hashcode 和 equals 麼,爲何重寫equals時必須重寫hashCode方法?」
hashCode() 的做用是獲取哈希碼,也稱爲散列碼;它其實是返回一個int整數。這個哈希碼的做用是肯定該對象在哈希表中的索引位置。hashCode() 定義在JDK的Object.java中,這就意味着Java中的任何類都包含有hashCode() 函數。
散列表存儲的是鍵值對(key-value),它的特色是:能根據「鍵」快速的檢索出對應的「值」。這其中就利用到了散列碼!(能夠快速找到所須要的對象)
咱們以「HashSet如何檢查重複」爲例子來講明爲何要有hashCode:
當你把對象加入HashSet時,HashSet會先計算對象的hashcode值來判斷對象加入的位置,同時也會與其餘已經加入的對象的hashcode值做比較,若是沒有相符的hashcode,HashSet會假設對象沒有重複出現。可是若是發現有相同hashcode值的對象,這時會調用equals()方法來檢查hashcode相等的對象是否真的相同。若是二者相同,HashSet就不會讓其加入操做成功。若是不一樣的話,就會從新散列到其餘位置。(摘自個人Java啓蒙書《Head fist java》第二版)。這樣咱們就大大減小了equals的次數,相應就大大提升了執行速度。
值傳遞是指對象被值傳遞,意味着傳遞了對象的一個副本,即便副本被改變,也不會影響源對象。(由於值傳遞的時候,其實是將實參的值複製一份給形參。)
引用傳遞是指對象被引用傳遞,意味着傳遞的並非實際的對象,而是對象的引用。所以,外部對引用對象的改變會反映到全部的對象上。(由於引用傳遞的時候,其實是將實參的地址值複製一份給形參。)
線程與進程類似,但線程是一個比進程更小的執行單位。一個進程在其執行的過程當中能夠產生多個線程。與進程不一樣的是同類的多個線程共享同一塊內存空間和一組系統資源,因此係統在產生一個線程,或是在各個線程之間做切換工做時,負擔要比進程小得多,也正由於如此,線程也被稱爲輕量級進程。
程序是含有指令和數據的文件,被存儲在磁盤或其餘的數據存儲設備中,也就是說程序是靜態的代碼。
進程是程序的一次執行過程,是系統運行程序的基本單位,所以進程是動態的。系統運行一個程序便是一個進程從建立,運行到消亡的過程。簡單來講,一個進程就是一個執行中的程序,它在計算機中一個指令接着一個指令地執行着,同時,每一個進程還佔有某些系統資源如CPU時間,內存空間,文件,文件,輸入輸出設備的使用權等等。換句話說,當程序在執行時,將會被操做系統載入內存中。 線程是進程劃分紅的更小的運行單位。線程和進程最大的不一樣在於基本上各進程是獨立的,而各線程則不必定,由於同一進程中的線程極有可能會相互影響。從另外一角度來講,進程屬於操做系統的範疇,主要是同一段時間內,能夠同時執行一個以上的程序,而線程則是在同一程序內幾乎同時執行一個以上的程序段。
備註: 能夠用早起坐地鐵來比喻這個過程:
還沒起牀:sleeping
起牀收拾好了,隨時能夠坐地鐵出發:Runnable
等地鐵來:Waiting
地鐵來了,但要排隊上地鐵:I/O阻塞
上了地鐵,發現暫時沒座位:synchronized阻塞
地鐵上找到座位:Running
到達目的地:Dead