一、面向對象和麪向過程的區別二、Java 語言有哪些特色?三、什麼是 Java 虛擬機?爲何 Java 被稱做是「平臺無關的編程語言」?四、JDK 和 JRE 的區別是什麼?五、Java 和 C++的區別?六、面向對象的特徵有哪些方面?七、訪問修飾符 public,private,protected,以及不寫(默認)時的區別?八、」static」關鍵字是什麼意思?Java 中是否能夠覆蓋(override)一個 private 或者是 static 的方法?九、是否能夠在 static 環境中訪問非 static 變量?十、Java 支持的數據類型有哪些?什麼是自動拆裝箱?十一、Java 中的方法覆蓋(Overriding)和方法重載(Overload)是什麼意思?十二、Java 中,什麼是構造方法?什麼是構造方法重載?什麼是複製構造方法?1三、Java支持多繼承麼?1四、什麼是值傳遞和引用傳遞?1五、== 和 equals 的區別是什麼?1六、爲何重寫 equals 時必須重寫 hashCode 方法?1七、final 在 Java 中有什麼做用?1八、java 中操做字符串都有哪些類?它們之間有什麼區別?1九、如何將字符串反轉?20、String 類的經常使用方法都有那些?2一、int和Integer有什麼區別?2二、靜態嵌套類(Static Nested Class)和內部類(Inner Class)的不一樣?2三、接口和抽象類的區別和相同點是什麼?2四、普通類和抽象類有哪些區別?2五、抽象類能使用 final 修飾嗎?2六、抽象的(abstract)方法是否可同時是靜態的(static),是否可同時是本地方法(native),是否可同時被 synchronized 修飾?2七、Java 有沒有 goto?2八、&和&&的區別?2九、Java 中 IO 流分爲幾種?30、BIO、NIO、AIO 有什麼區別?3一、Files的經常使用方法都有哪些?html
面向過程:面向過程性能比面向對象高。由於對象調用須要實例化,開銷比較大,較消耗資源,因此當性能是最重要的考量因素的時候,好比單片機、嵌入式開發、Linux/Unix 等,通常採用面向過程開發。可是,面向過程沒有面向對象易維護、易複用、易擴展。java
面向對象:面向對象易維護、易複用、易擴展。由於面向對象有封裝、繼承、多態性的特性,因此可設計出低耦合的系統,使得系統更加靈活、更加易於維護。程序員
面向過程性能比面向對象高的背後緣由?web
面向過程也須要分配內存,計算內存偏移量,Java 性能差的主要緣由並非由於它是面嚮對象語言,而是由於 Java 是半編譯語言,最終的執行代碼並非能夠直接被 CPU 執行的二進制機器碼。編程
而面向過程語言大多都是直接編譯成機器碼在電腦上執行,而且其它一些面向過程的腳本語言性能也並不必定比 Java 好。數組
擴展:爲何說 Java 語言編譯與解釋並存?緩存
當 .class 字節碼文件經過 JVM 轉爲機器能夠執行的二進制機器碼時,JVM 類加載器首先加載字節碼文件,而後經過解釋器逐行進行解釋執行,這種方式的執行速度相對比較慢。並且有些方法和代碼塊是反覆被調用的(也就是所謂的熱點代碼),因此後面引進了 JIT 編譯器,而 JIT 屬於運行時編譯。當 JIT 編譯器完成一次編譯後,會將字節碼對應的機器碼保存下來,下次能夠直接調用。這也解釋了咱們爲何常常會說 Java 是編譯與解釋共存的語言。安全
HotSpot採用了惰性評估(Lazy Evaluation)的作法,根據二八定律,消耗大部分系統資源的只有那一小部分的代碼(熱點代碼),而這也就是JIT所須要編譯的部分。JVM會根據代碼每次被執行的狀況收集信息並相應地作出一些優化,所以執行的次數越多,它的速度就越快。JDK 9引入了一種新的編譯模式AOT(Ahead of Time Compilation),它是直接將字節碼編譯成機器碼,這樣就避免了JIT預熱等各方面的開銷。JDK支持分層編譯和AOT協做使用。可是 ,AOT 編譯器的編譯質量是確定比不上 JIT 編譯器的。服務器
Java 虛擬機是一個能夠執行 Java 字節碼的虛擬機進程。Java 源文件被編譯成能被 Java 虛擬機執行的字節碼文件。網絡
Java 的跨平臺指的是 java 源文件通過 javac 編譯器編譯成的二進制.class 字節碼的跨平臺性。各個平臺裝有不一樣的 jvm,而 jvm 能將相同的字節碼翻譯成平臺相關的機器碼,進而執行。
Java 運行時環境(JRE)。它包括 Java 虛擬機、Java 核心類庫和支持文件。它不包含開發工具(JDK)--編譯器、調試器和其餘工具。
Java 開發工具包(JDK)是完整的 Java 軟件開發包,包含了 JRE,編譯器和其餘的工具(好比:JavaDoc,Java 調試器),可讓開發者開發、編譯、執行 Java 應用程序。
- 多態性分爲編譯時的多態性和運行時的多態性。
- 方法重載(overload)實現的是編譯時的多態性(也稱爲前綁定),而方法重寫(override)實現的是運行時的多態性(也稱爲後綁定)。
- 實現多態的技術:動態綁定,是指執行期間判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。
- 實現多態的條件:(1)繼承(2)方法重寫(3)父類引用指向子類對象。
- 多態的做用:消除類型之間的耦合關係。
private:類成員只能被當前類自己訪問,若是類的構造方法聲明爲 private,則其餘類不能生成該類的實例。
default:類成員能夠被這個類和同一個包中的類所訪問。
protected:類成員被同一個類,同一個包中的其餘類,子類(同包或不一樣包)訪問。
public:被全部類訪問。
static 表示靜態的意義,能夠修飾成員變量、成員方法、內部類和代碼塊,被 static 修飾的變量叫作靜態變量,隨類加載一次,能夠被多個對象共享。被其修飾的方法成爲靜態方法(類方法),其隨着類的加載而被加載,能夠經過類直接訪問,不須要實例化對象。此外靜態方法只能訪問靜態成員,不能夠直接訪問非靜態成員。靜態內部類能夠直接調用靜態構造器(不用對象)。靜態代碼塊只需加載一次,能夠有多個代碼塊。
重寫是子類中的方法和子類繼承的父類中的方法同樣(函數名,參數,參數類型,返回值類型),可是子類中的訪問權限要不低於父類中的訪問權限。重寫的前提是必需要繼承,private 修飾不支持繼承,所以被私有的方法不能夠被重寫。靜態方法形式上能夠被重寫,可是會被隱藏。緣由在於方法重寫基於運行時動態綁定,而 static 方法是編譯時靜態綁定的。
由於靜態的成員屬於類,隨着類的加載而加載到靜態方法區內存,當類加載時,此時不必定有實例建立,沒有實例,就不能夠直接訪問非靜態的成員。
最多見的 static 方法就是 main,做爲程序的入口,全部對象都是在該方法裏面實例化。
自動裝箱就是 Java 編譯器在基本數據類型和對應的對象包裝類型間的轉化,即 int 轉化爲 Integer,自動拆箱是 Integer 調用其方法將其轉化爲 int 的過程
方法重寫
方法重載
Java 中的構造函數是爲了初始化對象的,構造函數的函數名和類名一致,默認的構造函數沒有參數,沒有返回值,構造函數的函數體內,沒有內容。 構造函數的重載是函數名與類名相同,參數列表不一樣。一樣也是爲了初始化對象的。
關於複製構造函數:C++ 中的複製構造函數一般有三種做用
C++ 語法容許用戶定義本身的複製構造函數以實現自定義的複製,好比說進行深複製。Java 並不支持這樣的複製構造函數。可是這並不表明 Java 中沒有這種機制,在 Java 中 Object 類的 clone()方法就是這種機制的體現。並且經過以上三種方式對 Java 對象進行的操做都是對引用的操做,不像 C++ 裏面是對原對象的操做,所以 Java 中也不須要考慮須要使用複製構造函數這種問題。
Java 中類不支持多繼承,只支持單繼承(即一個類只有一個父類)。 可是 Java 中的接口支持多繼承,,即一個子接口能夠有多個父接口。(接口的做用是用來擴展對象的功能,一個子接口繼承多個父接口,說明子接口擴展了多個功能,當類實現接口時,類就擴展了相應的功能)。
值傳遞是對基本型變量而言的,傳遞的是該變量的一個副本,改變副本不影響原變量. 引用傳遞通常是對於引用型變量而言的,傳遞的是該對象地址的一個副本, 並非原對象自己 。通常認爲,Java 內的基礎類型數據傳遞都是值傳遞. Java 中實例對象的傳遞是引用傳遞
Java 編程語言只有值傳遞參數。當一個對象實例做爲一個參數被傳遞到方法中時,參數的值就是該對象的引用的一個副本。指向同一個對象,對象的內容能夠在被調用的方法中改變,但對象的引用(不是引用的副本)是永遠不會改變的。
當基本型變量做爲參數傳遞到方法中時,參數的值是該變量的副本,改變副本不影響原變量。
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
builder = new StringBuilder("ipad");
}
foo(sb); // sb 沒有被改變,仍是 "iphone"。
複製代碼
推薦閱讀:Java中只有按值傳遞,沒有按引用傳遞!
基本數據類型,也稱原始數據類型。byte,short,char,int,long,float,double,boolean 它們之間的比較,應用雙等號(==),比較的是它們的值。
複合數據類型(類)。當它們用雙等號進行比較的時候,比較的是它們在內存中的存放地址,因此,除非是同一個 new 出來的對象,它們的比較後的結果爲 true,不然比較後結果爲 false。 Java 當中全部的類都是繼承於 Object 這個基類的,在 Object 中的基類中定義了一個 equals 的方法,這個方法的初始行爲是比較對象的內存地址,但在一些類庫當中這個方法被覆蓋掉了,如 String,Integer,Date 在這些類當中 equals 有其自身的實現(在重寫 equals 方法的時候,有必要重寫對象的 hashCode 方法,從而保證程序完整性),而再也不是比較類在堆內存中的存放地址了。
hashCode()與equals()的相關規定:
爲何要有 hashCode?
咱們先以「HashSet 如何檢查重複」爲例子來講明爲何要有 hashCode: 當你把對象加入 HashSet 時,HashSet 會先計算對象的 hashcode 值來判斷對象加入的位置,同時也會與其餘已經加入的對象的 hashcode 值做比較,若是沒有相同的 hashcode,HashSet 會假設對象沒有重複出現。可是若是發現有相同 hashcode 值的對象,這時會調用 equals()方法來檢查 hashcode 相等的對象是否真的相同。若是二者相同,HashSet 就不會讓其加入操做成功。若是不一樣的話,就會從新散列到其餘位置。(摘自個人Java啓蒙書《Head first java》第二版)。這樣咱們就大大減小了 equals 的次數,相應就大大提升了執行速度。
經過咱們能夠看出:hashCode() 的做用就是獲取哈希碼,也稱爲散列碼;它其實是返回一個 int 整數。這個哈希碼的做用是肯定該對象在哈希表中的索引位置。hashCode()在散列表中才有用,在其它狀況下沒用。在散列表中 hashCode() 的做用是獲取對象的散列碼,進而肯定該對象在散列表中的位置。
繼續上面的話題,爲何必需要重寫 hashcode 方法,其實簡單的說就是爲了保證同一個對象,保證在 equals 相同的狀況下 hashcode 值一定相同,若是重寫了 equals 而未重寫 hashcode 方法,可能就會出現兩個沒有關係的對象 equals 相同的(由於 equals 都是根據對象的特徵進行重寫的),但 hashcode 確實不相同的。
- 當用 final 修飾一個類時,代表這個類不能被繼承。
- final 修飾的方法不能被重寫。
- final 修飾的變量叫常量,常量必須初始化,初始化以後值就不能被修改。
操做字符串的類有:String
、StringBuffer
、StringBuilder
。
String 和 StringBuffer、StringBuilder 的區別在於 String 聲明的是不可變的對象,每次操做都會生成新的 String 對象,而後將指針指向新的 String 對象,而 StringBuffer、StringBuilder 能夠在原有對象的基礎上進行操做,因此在常常改變字符串內容的狀況下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的區別在於,StringBuffer 是線程安全的,而 StringBuilder 是非線程安全的,但 StringBuilder 的性能卻高於 StringBuffer,因此在單線程環境下推薦使用 StringBuilder,多線程環境下推薦使用 StringBuffer。
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
indexOf():返回指定字符的索引。
charAt():返回指定索引處的字符。
replace():字符串替換。
trim():去除字符串兩端空白。
split():分割字符串,返回一個分割後的字符串數組。
getBytes():返回字符串的 byte 類型數組。
length():返回字符串長度。
toLowerCase():將字符串轉成小寫字母。
toUpperCase():將字符串轉成大寫字符。
substring():截取字符串。
equals():字符串比較
public class Test03 {
public static void main(String[] args) {
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);
System.out.println(f3 == f4);
}
//結果
true
false
複製代碼
Java 在編譯 Integer i = 100 ;時,會翻譯成爲 Integer i = Integer.valueOf(100)。根據 Java API 中對 Integer 類型的 valueOf 的定義可知,當數值在[-128,127]範圍內時,Integer 對象會存儲在緩存中,f1 和 f2 都指向的是緩存中同一個對象,而不會 new 個新對象。反之若是不在該範圍內,f3 和 f4 指向兩個不一樣的對象。
Static Nested Class 是被聲明爲靜態(static)的內部類,它能夠不依賴於外部類實例被實例化。而一般的內部類須要在外部類實例化後才能實例化。
class Outer {
class Inner {}
public static void foo() {
new Inner(); //編譯報錯
}
public void bar() {
new Inner();
}
public static void main(String[] args) {
new Inner();//編譯報錯
}
}
複製代碼
Java 中非靜態內部類對象的建立要依賴其外部類對象,上述代碼中 foo 和 main 方法都是靜態方法,靜態方法中沒有 this,也就是說沒有所謂的外部類對象,所以沒法建立內部類對象,若是要在靜態方法中建立內部類對象,能夠這樣作:new Outer().new Inner();
接口和抽象類的區別
相同點:
普通類不能包含抽象方法,抽象類能夠包含抽象方法。
抽象類不能直接實例化,普通類能夠直接實例化。
不能,定義抽象類就是讓其餘類繼承的,若是定義爲 final 該類就不能被繼承,這樣彼此就會產生矛盾,因此 final 不能修飾抽象類。
都不能。抽象方法須要子類重寫,而靜態的方法是沒法被重寫的,所以兩者是矛盾的。本地方法是由本地代碼(如 C 代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized 和方法的實現細節有關,抽象方法不涉及實現細節,所以也是相互矛盾的。
goto 是 Java 中的保留字,在目前版本的 Java 中沒有使用。
&運算符有兩種用法:(1)按位與;(2)邏輯與。&&運算符是短路與運算。邏輯與跟短路與的差異是很是巨大的,雖然兩者都要求運算符左右兩端的布爾值都是 true 整個表達式的值纔是 true。&&之因此稱爲短路運算是由於,若是&&左邊的表達式的值是 false,右邊的表達式會被直接短路掉,不會進行運算。注意:邏輯或運算符(|)和短路或運算符(||)的差異也是如此。
字節流和字符流的區別是:字節流按 8 位傳輸以字節爲單位輸入輸出數據,字符流按 16 位傳輸以字符爲單位輸入輸出數據。
節點流:能夠從或向一個特定的地方(節點)讀寫數據。如 FileReader。處理流:是對一個已存在的流的鏈接和封裝,經過所封裝的流的功能調用實現數據讀寫。如 BufferedReader。處理流的構造方法老是要帶一個其餘的流對象作參數。一個流對象通過其餘流的屢次包裝,稱爲流的連接。
推薦閱讀:JAVA的節點流和處理流
Java IO 流共涉及 40 多個類,這些類看上去很雜亂,但實際上頗有規則,並且彼此之間存在很是緊密的聯繫, Java I0 流的 40 多個類都是從以下 4 個抽象類基類中派生出來的。
按操做方式分類結構圖:
按操做對象分類結構圖:
BIO:Block IO 同步阻塞式 IO,就是咱們日常使用的傳統 IO,它的特色是模式簡單使用方便,併發處理能力低。
NIO:New IO 同步非阻塞 IO,是傳統 IO 的升級,客戶端和服務器端經過 Channel(通道)通信,實現了多路複用。在Java 1.4 中引入了 NIO 框架,對應 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N能夠理解爲Non-blocking,不單純是New。它支持面向緩衝的,基於通道的I/O操做方法。 NIO提供了與傳統BIO模型中的 Socket 和 ServerSocket 相對應的 SocketChannel 和 ServerSocketChannel 兩種不一樣的套接字通道實現,兩種通道都支持阻塞和非阻塞兩種模式。對於高負載、高併發的(網絡)應用,應使用 NIO 的非阻塞模式來開發。
AIO:Asynchronous IO 是 NIO 的升級,也叫 NIO2,在 Java 7 中引入了 NIO 的改進版 NIO 2,它是異步非阻塞的IO模型。異步 IO 是基於事件和回調機制實現的,也就是應用操做以後會直接返回,不會堵塞在那裏,當後臺處理完成,操做系統會通知相應的線程進行後續的操做。AIO 是異步 IO 的縮寫,雖然 NIO 在網絡操做中,提供了非阻塞的方法,可是 NIO 的 IO 行爲仍是同步的。對於 NIO 來講,咱們的業務線程是在 IO 操做準備好時,獲得通知,接着就由這個線程自行進行 IO 操做,IO操做自己是同步的。