1.面向對象和麵向過程的區別? 面向過程:面向過程性能比面向對象高 面向對象:面向對象易維護、易復用、易擴展 面向過程:面向過程性能比面向對象高 面向對象:面向對象易維護、易復用、易擴展 2.Java 語言有哪些特點? 簡單易學、面向對象(封裝,繼承,多態)、平臺無關性( Java 虛擬機實現平臺無 ...
1.面向對象和麵向過程的區別?
- 面向過程:面向過程性能比面向對象高
- 面向對象:面向對象易維護、易復用、易擴展
2.Java 語言有哪些特點? 簡單易學、面向對象(封裝,繼承,多態)、平臺無關性( Java 虛擬機實現平臺無關性)、可靠性、安全性、支持多線程、支持網路編程並且很方便、編譯與解釋並存。
3.JDK和JRE?
- JDK:Java Development Kit,它是功能齊全的Java SDK。它擁有JRE所擁有的一切,還有編譯器(javac)和工具(如javadoc和jdb)。它能夠創建和編譯程式。
- JRE 是 Java運行時環境。它是運行已編譯 Java 程式所需的所有內容的集合,包括 Java虛擬機(JVM),Java類庫,java命令和其他的一些基礎構件。但是,它不能用於創建新程式。
4.Java和C++的區別?
- 都是面向對象的語言,都支持封裝、繼承和多態
- Java 不提供指針來直接訪問記憶體,程式記憶體更加安全
- Java 的類是單繼承的,C++ 支持多重繼承;雖然 Java 的類不可以多繼承,但是介面可以多繼承。
- Java 有自動記憶體管理機制,不需要程式員手動釋放無用記憶體。
5.Java 面向對象三大特性 封裝 繼承 多態
- 封裝:利用抽象數據類型將數據和操作數據的方法綁定起來,數據被保護在抽象數據類型的內部,儘可能地隱藏內部的細節,對數據的訪問只能通過已定義的介面。
- 繼承:使用已存在的類的定義作為基礎建立新類,新類的定義可以增加新的數據或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。通過使用繼承我們能夠非常方便地復用以前的代碼。 關於繼承需要註意的點: 子類擁有父類對象所有的屬性和方法,但是父類中的私有屬性和方法子類是無法訪問,只是擁有。 子類可以擁有自己屬性和方法,即子類可以對父類進行擴展。 子類可以擁有自己屬性和方法,即子類可以對父類進行擴展。
- 多態:允許不同子類型的對象對同一消息作出不同響應。也就是,用同樣的對象引用調用同樣的方法但是做了不同的事情。 多態有兩種實現方式: 繼承,即多個子類對同一方法的重寫; 介面,即實現介面並覆蓋介面中同一方法;
6.抽象類和介面的區別? 相同點:
- 都不能直接實例化對象;
- 都包含抽象方法,其子類都必須覆寫這些抽象方法;
- 抽象類為部分方法提供實現,避免子類重覆實現這些方法,提高代碼重用性;介面只能包含抽象方法;
- 一個類只能繼承一個直接父類(可能是抽象類),卻可以實現多個介面;(介面彌補了Java的單繼承);
- 介面是這個事物中的額外內容,繼承體系是一種 like..a關係
- 抽象類是這個事物中應該具備的你內容, 繼承體系是一種 is..a關係
7.抽象類可以用final修飾嗎?可以有static方法嗎?可以創建抽象類的實例嗎?抽象類必須有抽象方法嗎? (1)抽象類不能是final的,將它們聲明為final的將會阻止它們被繼承,而這正是使用抽象類唯一的方法,它們也是彼此相反的,關鍵字abstract強制繼承類,而關鍵字final阻止類被擴張。Java類不能既是final又是abstract的,編譯時會報錯。 (2)抽象類可以定義static方法,但此static方法無法沒繼承。 (3)不能創建抽象類的實例,即使抽象類不包含抽象方法,也不能實例化抽象類,否則編譯時會報錯。 (4)抽象類不強制性有抽象方法。只要使用關鍵字abstract就可以將類聲明為抽象類。
8.重載和重寫的區別
- 重載: 發生在同一個類中,方法名必須相同,參數類型不同、個數不同、順序不同,方法返回值和訪問修飾符可以不同,發生在編譯時。
- 重寫: 發生在父子類中,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類;如果父類方法訪問修飾符為 private 則子類就不能重寫該方法。
9.在 Java 中定義一個不做事且沒有參數的構造方法的作用? Java 程式在執行子類的構造方法之前,如果沒有用
super()
來調用父類特定的構造方法,則會調用父類中“沒有參數的構造方法”。因此,如果父類中只定義了有參數的構造方法,而在子類的構造方法中又沒有用 super()
來調用父類中特定的構造方法,則編譯時將發生錯誤,因為 Java 程式在父類中找不到沒有參數的構造方法可供執行。解決辦法是在父類裡加上一個不做事且沒有參數的構造方法。
10.String StringBuffer 和 StringBuilder 的區別是什麼? String 為什麼是不可變的?
- 線程安全性:String 中的對象是不可變的,也就可以理解為常量,線程安全。AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類,定義了一些字元串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的。StringBuilder 並沒有對方法進行加同步鎖,所以是非線程安全的。
- 性能:每次對 String 類型進行改變的時候,都會生成一個新的 String 對象,然後將指針指向新的 String 對象。StringBuffer 每次都會對 StringBuffer 對象本身進行操作,而不是生成新的對象並改變對象引用。相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。
- 可變性:String 類中使用 final 關鍵字修飾字元數組來保存字元串,
private final char value[]
,所以 String 對象是不可變的。而StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字元數組保存字元串char[]value
但是沒有用 final 關鍵字修飾,所以這兩種對象都是可變的。
11.成員變數與局部變數的區別有哪些?
- 從語法形式上看:成員變數是屬於類的,而局部變數是在方法中定義的變數或是方法的參數;成員變數可以被 public,private,static 等修飾符所修飾,而局部變數不能被訪問控制修飾符及 static 所修飾;但是,成員變數和局部變數都能被 final 所修飾。
- 從變數在記憶體中的存儲方式來看:如果成員變數是使用
static
修飾的,那麼這個成員變數是屬於類的,如果沒有使用static
修飾,這個成員變數是屬於實例的。而對象存在於堆記憶體,局部變數則存在於棧記憶體。 - 從變數在記憶體中的生存時間上看:成員變數是對象的一部分,它隨著對象的創建而存在,而局部變數隨著方法的調用而自動消失。
- 成員變數如果沒有被賦初值:則會自動以類型的預設值而賦值(一種情況例外:被 final 修飾的成員變數也必須顯式地賦值),而局部變數則不會自動賦值。
12.一個類的構造方法的作用是什麼? 若一個類沒有聲明構造方法,該程式能正確執行嗎? 為什麼? 構造方法有哪些特性? (1)主要作用是完成對類對象的初始化工作。可以執行。因為一個類即使沒有聲明構造方法也會有預設的不帶參數的構造方法。 (2)構造方法的特性:
- 名字和類名相同;
- 沒有返回值,但不能用void聲明構造函數。
- 生成類的對象時自動執行,無需調用。
13.靜態方法和實例方法有何不同?
- 在外部調用靜態方法時,可以使用"類名.方法名"的方式,也可以使用"對象名.方法名"的方式。而實例方法只有後面這種方式。也就是說,調用靜態方法可以無需創建對象。
- 靜態方法在訪問本類的成員時,只允許訪問靜態成員(即靜態成員變數和靜態方法),而不允許訪問實例成員變數和實例方法;實例方法則無此限制。
13. == 與equals的區別?
- == : 它的作用是判斷兩個對象的地址是不是相等。即,判斷兩個對象是不是同一個對象(基本數據類型==比較的是值,引用數據類型==比較的是記憶體地址)。
- equals() : 它的作用也是判斷兩個對象是否相等。但它一般有兩種使用情況:
(1)情況1:類沒有覆蓋 equals() 方法。則通過 equals() 比較該類的兩個對象時,等價於通過“==”比較這兩個對象。
(2)情況2:類覆蓋了 equals() 方法。一般我們都覆蓋 equals() 方法來比較兩個對象的內容是否相等;若它們的內容相等,則返回 true (即,認為這兩個對象相等)。
14.hashCode()與equals()的區別? 從性能和可靠性進行分析:
- 重寫equals()方法時性能比較低,而利用hashCode()進行對比,則只要生成一個hash值進行比較就可以了,效率很高。
- hashCode()並不是完全可靠,有時候不同的對象生成的hashcode也會一樣,所以hashCode()只能說是大部分時候可靠,並不是絕對可靠。所以有以下結論:
(1)equals()相等的兩個對象他們的hashCode()肯定相等,也就是用equals()對比是絕對可靠的;
(2)hashCode()相等的兩個對象他們的equals()不一定相等,也就是hashCode()不是絕對可靠的。
- 若重寫了equals(Object obj)方法,則有必要重寫hashCode()方法。
- 若兩個對象equals(Object obj)返回true,則hashCode()有必要也返回相同的int數。
- 若兩個對象equals(Object obj)返回false,則hashCode()不一定返回不同的int數。
- 若兩個對象hashCode()返回相同int數,則equals(Object obj)不一定返回true。
- 若兩個對象hashCode()返回不同int數,則equals(Object obj)一定返回false。
- 同一對象在執行期間若已經存儲在集合中,則不能修改影響hashCode值的相關信息,否則會導致記憶體泄露問題。
15.hashCode()的作用? hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實際上是返回一個int整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode() 定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode() 函數。hashCode() 在散列表中才有用,在其它情況下沒用。在散列表中hashCode() 的作用是獲取對象的散列碼,進而確定該對象在散列表中的位置。
16.final關鍵字的作用?
- 對於一個final變數,如果是基本數據類型的變數,則其數值一旦在初始化之後便不能更改;如果是引用類型的變數,則在對其初始化之後便不能再讓其指向另一個對象。
- 當用final修飾一個類時,表明這個類不能被繼承。final類中的所有成員方法都會被隱式地指定為final方法。
- 使用final方法的原因有兩個。第一個原因是把方法鎖定,以防任何繼承類修改它的含義;第二個原因是效率。在早期的Java實現版本中,會將final方法轉為內嵌調用。但是如果方法過於龐大,可能看不到內嵌調用帶來的任何性能提升(現在的Java版本已經不需要使用final方法進行這些優化了)。類中所有的private方法都隱式地指定為final。
17.Java中的異常處理? 所有的異常是Throwable類。Throwable: 有兩個重要的子類:Exception(異常) 和 Error(錯誤) ,二者都是 Java 異常處理的重要子類,各自都包含大量子類。
- Error:程式無法處理的錯誤。表示運行應用程式中較嚴重問題,大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運行時 JVM(Java 虛擬機)出現的問題。
- Exception:程式本身可以處理的異常。xception 類有一個重要的子類 RuntimeException。RuntimeException 異常由Java虛擬機拋出。NullPointerException(要訪問的變數沒有引用任何對象時,拋出該異常)、ArithmeticException(算術運算異常,一個整數除以0時,拋出該異常)和 ArrayIndexOutOfBoundsException (下標越界異常)。
- 在finally語句塊第一行發生了異常。 因為在其他行,finally塊還是會得到執行;
- 在前面的代碼中用了System.exit(int)已退出程式。 若該語句在異常語句之後,finally會執行;
- 程式所在的線程死亡;
- 關閉CPU;
18.BIO、NIO、AIO有什麼區別?
- BIO (Blocking I/O): 同步阻塞I/O模式,數據的讀取寫入必須阻塞在一個線程內等待其完成。在活動連接數不是特別高(小於單機1000)的情況下,這種模型是比較不錯的,可以讓每一個連接專註於自己的 I/O 並且編程模型簡單,也不用過多考慮系統的過載、限流等問題。線程池本身就是一個天然的漏斗,可以緩衝一些系統處理不了的連接或請求。但是,當面對十萬甚至百萬級連接的時候,傳統的 BIO 模型是無能為力的。因此,我們需要一種更高效的 I/O 處理模型來應對更高的併發量。
- NIO (New I/O): NIO是一種同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,對應 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解為Non-blocking,不單純是New。它支持面向緩衝的,基於通道的I/O操作方法。 NIO提供了與傳統BIO模型中的
Socket
和ServerSocket
相對應的SocketChannel
和ServerSocketChannel
兩種不同的套接字通道實現,兩種通道都支持阻塞和非阻塞兩種模式。阻塞模式使用就像傳統中的支持一樣,比較簡單,但是性能和可靠性都不好;非阻塞模式正好與之相反。對於低負載、低併發的應用程式,可以使用同步阻塞I/O來提升開發速率和更好的維護性;對於高負載、高併發的(網路)應用,應使用 NIO 的非阻塞模式來開發。 - AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改進版 NIO 2,它是非同步非阻塞的IO模型。非同步 IO 是基於事件和回調機制實現的,也就是應用操作之後會直接返回,不會堵塞在那裡,當後臺處理完成,操作系統會通知相應的線程進行後續的操作。AIO 是非同步IO的縮寫,雖然 NIO 在網路操作中,提供了非阻塞的方法,但是 NIO 的 IO 行為還是同步的。對於 NIO 來說,我們的業務線程是在 IO 操作准備好時,得到通知,接著就由這個線程自行進行 IO 操作,IO操作本身是同步的。