Java 基礎(理論篇)

一、面向對象和麪向過程的區別二、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 語言有哪些特色?

  • 簡單易學(其實相比較 Python 仍是更容易上手一些)
  • 面向對象(封裝、繼承、抽象、多態)
  • 平臺無關性(Java 虛擬機實現字節碼文件的跨平臺)
  • 安全可靠性
  • 支持多線程(C++語言沒有內置的多線程機制,所以必須調用操做系統的多線程功能來進行多線程程序設計,而 Java 語言卻提供了多線程支持)
  • 支持網絡編程而且很方便(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 虛擬機執行的字節碼文件。網絡

Java 的跨平臺指的是 java 源文件通過 javac 編譯器編譯成的二進制.class 字節碼的跨平臺性。各個平臺裝有不一樣的 jvm,而 jvm 能將相同的字節碼翻譯成平臺相關的機器碼,進而執行。


四、JDK 和 JRE 的區別是什麼?

Java 運行時環境(JRE)。它包括 Java 虛擬機、Java 核心類庫和支持文件。它不包含開發工具(JDK)--編譯器、調試器和其餘工具。

Java 開發工具包(JDK)是完整的 Java 軟件開發包,包含了 JRE,編譯器和其餘的工具(好比:JavaDoc,Java 調試器),可讓開發者開發、編譯、執行 Java 應用程序。


五、Java 和 C++的區別?

  • 都是面向對象的語言,都支持封裝、繼承和多態;
  • Java 不提供指針來直接訪問內存,程序內存更加安全;
  • Java 的類是單繼承的,C++ 支持多重繼承;雖然 Java 的類不能夠多繼承,可是接口能夠多繼承;
  • Java 有自動內存管理機制,不須要程序員手動釋放無用內存。

六、面向對象的特徵有哪些方面?

  1. 封裝:一般認爲封裝是把數據和操做數據的方法綁定起來,對數據的訪問只能經過已定義的接口。
  2. 繼承:繼承是從已有類獲得繼承信息建立新類的過程。提供繼承信息的類被稱爲父類(超類、基類);獲得繼承信息的類被稱爲子類(派生類)。
  3. 抽象:抽象是將一類對象的共同特徵總結出來構造類的過程,包括數據抽象和行爲抽象兩方面。抽象只關注對象有哪些屬性和行爲,並不關注這些行爲的細節是什麼。
  4. 多態性:多態性是指容許不一樣子類型的對象對同一消息做出不一樣的響應。即同一消息能夠根據發送對象的不一樣而採起不一樣的行爲方式。
  • 多態性分爲編譯時的多態性和運行時的多態性。
  • 方法重載(overload)實現的是編譯時的多態性(也稱爲前綁定),而方法重寫(override)實現的是運行時的多態性(也稱爲後綁定)。
  • 實現多態的技術:動態綁定,是指執行期間判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。
  • 實現多態的條件:(1)繼承(2)方法重寫(3)父類引用指向子類對象。
  • 多態的做用:消除類型之間的耦合關係。

七、訪問修飾符 public,private,protected,以及不寫(默認)時的區別?

private:類成員只能被當前類自己訪問,若是類的構造方法聲明爲 private,則其餘類不能生成該類的實例。
default:類成員能夠被這個類和同一個包中的類所訪問。
protected:類成員被同一個類,同一個包中的其餘類,子類(同包或不一樣包)訪問。
public:被全部類訪問。


八、」static」關鍵字是什麼意思?Java 中是否能夠覆蓋(override)一個 private 或者是 static 的方法?

static 表示靜態的意義,能夠修飾成員變量、成員方法、內部類和代碼塊,被 static 修飾的變量叫作靜態變量,隨類加載一次,能夠被多個對象共享。被其修飾的方法成爲靜態方法(類方法),其隨着類的加載而被加載,能夠經過類直接訪問,不須要實例化對象。此外靜態方法只能訪問靜態成員,不能夠直接訪問非靜態成員。靜態內部類能夠直接調用靜態構造器(不用對象)。靜態代碼塊只需加載一次,能夠有多個代碼塊。

重寫是子類中的方法和子類繼承的父類中的方法同樣(函數名,參數,參數類型,返回值類型),可是子類中的訪問權限要不低於父類中的訪問權限。重寫的前提是必需要繼承,private 修飾不支持繼承,所以被私有的方法不能夠被重寫。靜態方法形式上能夠被重寫,可是會被隱藏。緣由在於方法重寫基於運行時動態綁定,而 static 方法是編譯時靜態綁定的。


九、是否能夠在 static 環境中訪問非 static 變量?

由於靜態的成員屬於類,隨着類的加載而加載到靜態方法區內存,當類加載時,此時不必定有實例建立,沒有實例,就不能夠直接訪問非靜態的成員。

最多見的 static 方法就是 main,做爲程序的入口,全部對象都是在該方法裏面實例化。


十、Java 支持的數據類型有哪些?什麼是自動拆裝箱?

  • 基本數據類型:byte,short,char,int,long,float,double,boolean。
  • 引用數據類型:Integer、String 等。引用類型實體在堆中,聲明的變量存放的是該對象的引用地址。

自動裝箱就是 Java 編譯器在基本數據類型和對應的對象包裝類型間的轉化,即 int 轉化爲 Integer,自動拆箱是 Integer 調用其方法將其轉化爲 int 的過程


十一、Java 中的方法覆蓋(Overriding)和方法重載(Overload)是什麼意思?

方法重寫

  • 方法名,參數列表必須相同,返回類型能夠相同也能夠是原類型的子類型
  • 重寫方法不能比原方法訪問性差(即訪問權限不容許縮小)。
  • 重寫方法不能比原方法拋出更多的異常。
  • 重寫發生在子類和父類之間
  • 重寫實現運行時的多態性

方法重載

  • 方法名必須相同,參數列表必須不一樣(個數不一樣、或類型不一樣、參數類型排列順序不一樣等)
  • 方法的返回類型能夠相同也能夠不相同。
  • 重載發生在同一類中
  • 重載實現編譯時的多態性

十二、Java 中,什麼是構造方法?什麼是構造方法重載?什麼是複製構造方法?

Java 中的構造函數是爲了初始化對象的,構造函數的函數名和類名一致,默認的構造函數沒有參數,沒有返回值,構造函數的函數體內,沒有內容。 構造函數的重載是函數名與類名相同,參數列表不一樣。一樣也是爲了初始化對象的。

關於複製構造函數:C++ 中的複製構造函數一般有三種做用

  1. 對象做爲函數參數
  2. 對象做爲函數返回值
  3. 使用一個對象對另外一個對象初始化。

C++ 語法容許用戶定義本身的複製構造函數以實現自定義的複製,好比說進行深複製。Java 並不支持這樣的複製構造函數。可是這並不表明 Java 中沒有這種機制,在 Java 中 Object 類的 clone()方法就是這種機制的體現。並且經過以上三種方式對 Java 對象進行的操做都是對引用的操做,不像 C++ 裏面是對原對象的操做,所以 Java 中也不須要考慮須要使用複製構造函數這種問題。


1三、Java支持多繼承麼?

Java 中類不支持多繼承,只支持單繼承(即一個類只有一個父類)。 可是 Java 中的接口支持多繼承,,即一個子接口能夠有多個父接口。(接口的做用是用來擴展對象的功能,一個子接口繼承多個父接口,說明子接口擴展了多個功能,當類實現接口時,類就擴展了相應的功能)。


1四、什麼是值傳遞和引用傳遞?

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

Java 編程語言只有值傳遞參數。當一個對象實例做爲一個參數被傳遞到方法中時,參數的值就是該對象的引用的一個副本。指向同一個對象,對象的內容能夠在被調用的方法中改變,但對象的引用(不是引用的副本)是永遠不會改變的。

當基本型變量做爲參數傳遞到方法中時,參數的值是該變量的副本,改變副本不影響原變量。

StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder = new StringBuilder("ipad");
}
foo(sb); // sb 沒有被改變,仍是 "iphone"。
複製代碼

推薦閱讀:Java中只有按值傳遞,沒有按引用傳遞!


1五、== 和 equals 的區別是什麼?

基本數據類型,也稱原始數據類型。byte,short,char,int,long,float,double,boolean 它們之間的比較,應用雙等號(==),比較的是它們的值。

複合數據類型(類)。當它們用雙等號進行比較的時候,比較的是它們在內存中的存放地址,因此,除非是同一個 new 出來的對象,它們的比較後的結果爲 true,不然比較後結果爲 false。 Java 當中全部的類都是繼承於 Object 這個基類的,在 Object 中的基類中定義了一個 equals 的方法,這個方法的初始行爲是比較對象的內存地址,但在一些類庫當中這個方法被覆蓋掉了,如 String,Integer,Date 在這些類當中 equals 有其自身的實現(在重寫 equals 方法的時候,有必要重寫對象的 hashCode 方法,從而保證程序完整性),而再也不是比較類在堆內存中的存放地址了。


1六、爲何重寫 equals 時必須重寫 hashCode 方法?

hashCode()與equals()的相關規定:

  • 若是兩個對象相等(即用 equals 比較返回 true),則 hashcode 必定也是相同的;
  • 兩個對象有相同的 hashcode 值,它們也不必定是相等的(不一樣的對象也可能產生相同的 hashcode,機率性問題);
  • equals 方法被覆蓋過,則 hashCode 方法也必須被覆蓋。

爲何要有 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 確實不相同的。


1七、final 在 Java 中有什麼做用?

  1. 當用 final 修飾一個類時,代表這個類不能被繼承。
  2. final 修飾的方法不能被重寫。
  3. final 修飾的變量叫常量,常量必須初始化,初始化以後值就不能被修改。

1八、java 中操做字符串都有哪些類?它們之間有什麼區別?

操做字符串的類有:StringStringBufferStringBuilder

String 和 StringBuffer、StringBuilder 的區別在於 String 聲明的是不可變的對象,每次操做都會生成新的 String 對象,而後將指針指向新的 String 對象,而 StringBuffer、StringBuilder 能夠在原有對象的基礎上進行操做,因此在常常改變字符串內容的狀況下最好不要使用 String。

StringBuffer 和 StringBuilder 最大的區別在於,StringBuffer 是線程安全的,而 StringBuilder 是非線程安全的,但 StringBuilder 的性能卻高於 StringBuffer,因此在單線程環境下推薦使用 StringBuilder,多線程環境下推薦使用 StringBuffer。


1九、如何將字符串反轉?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。


20、String 類的經常使用方法都有那些?

indexOf():返回指定字符的索引。

charAt():返回指定索引處的字符。

replace():字符串替換。

trim():去除字符串兩端空白。

split():分割字符串,返回一個分割後的字符串數組。

getBytes():返回字符串的 byte 類型數組。

length():返回字符串長度。

toLowerCase():將字符串轉成小寫字母。

toUpperCase():將字符串轉成大寫字符。

substring():截取字符串。

equals():字符串比較


2一、int和Integer有什麼區別?

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 指向兩個不一樣的對象。


2二、靜態嵌套類(Static Nested Class)和內部類(Inner Class)的不一樣?

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();

2三、接口和抽象類的區別和相同點是什麼?

接口和抽象類的區別

  1. 從設計層面來講,抽象是對類的抽象,是一種模板設計,接口是行爲的抽象,是一種行爲的規範。
  2. 定義接口的關鍵字是 interface ,抽象類的關鍵字是 abstract class
  3. 接口中全部的方法隱含的都是抽象的。而抽象類則能夠同時包含抽象和非抽象的方法。
  4. 類能夠實現不少個接口,可是隻能繼承一個抽象類
  5. Java 接口中聲明的變量默認都是 final 的。抽象類能夠包含非 final 的變量。
  6. Java 接口中的成員函數默認是 public 的。抽象類的成員函數能夠是 private,protected 或者是 public。

相同點:

  1. 接口是絕對抽象的,不能夠被實例化,抽象類也不能夠被實例化。
  2. 類能夠不實現抽象類和接口聲明的全部方法,固然,在這種狀況下,類也必須得聲明成是抽象的。

2四、普通類和抽象類有哪些區別?

普通類不能包含抽象方法,抽象類能夠包含抽象方法。

抽象類不能直接實例化,普通類能夠直接實例化。


2五、抽象類能使用 final 修飾嗎?

不能,定義抽象類就是讓其餘類繼承的,若是定義爲 final 該類就不能被繼承,這樣彼此就會產生矛盾,因此 final 不能修飾抽象類。


2六、抽象的(abstract)方法是否可同時是靜態的(static),是否可同時是本地方法(native),是否可同時被 synchronized 修飾?

都不能。抽象方法須要子類重寫,而靜態的方法是沒法被重寫的,所以兩者是矛盾的。本地方法是由本地代碼(如 C 代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized 和方法的實現細節有關,抽象方法不涉及實現細節,所以也是相互矛盾的。


2七、Java 有沒有 goto?

goto 是 Java 中的保留字,在目前版本的 Java 中沒有使用。


2八、&和&&的區別?

&運算符有兩種用法:(1)按位與;(2)邏輯與。&&運算符是短路與運算。邏輯與跟短路與的差異是很是巨大的,雖然兩者都要求運算符左右兩端的布爾值都是 true 整個表達式的值纔是 true。&&之因此稱爲短路運算是由於,若是&&左邊的表達式的值是 false,右邊的表達式會被直接短路掉,不會進行運算。注意:邏輯或運算符(|)和短路或運算符(||)的差異也是如此。


2九、Java 中 IO 流分爲幾種?

  • 按功能來分:輸入流(input)、輸出流(output)。
  • 按類型來分:字節流和字符流。
  • 按照流的角色劃分爲節點流和處理流。

字節流和字符流的區別是:字節流按 8 位傳輸以字節爲單位輸入輸出數據,字符流按 16 位傳輸以字符爲單位輸入輸出數據。

節點流:能夠從或向一個特定的地方(節點)讀寫數據。如 FileReader。處理流:是對一個已存在的流的鏈接和封裝,經過所封裝的流的功能調用實現數據讀寫。如 BufferedReader。處理流的構造方法老是要帶一個其餘的流對象作參數。一個流對象通過其餘流的屢次包裝,稱爲流的連接。

推薦閱讀:JAVA的節點流和處理流

Java IO 流共涉及 40 多個類,這些類看上去很雜亂,但實際上頗有規則,並且彼此之間存在很是緊密的聯繫, Java I0 流的 40 多個類都是從以下 4 個抽象類基類中派生出來的。

  • InputStream/Reader: 全部輸入流的基類,前者是字節輸入流,後者是字符輸入流。
  • OutputStream/Writer: 全部輸出流的基類,前者是字節輸出流,後者是字符輸出流。

按操做方式分類結構圖:

按操做對象分類結構圖:


30、BIO、NIO、AIO 有什麼區別?

  • 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操做自己是同步的。


3一、Files的經常使用方法都有哪些?

  • Files.exists():檢測文件路徑是否存在。
  • Files.createFile():建立文件。
  • Files.createDirectory():建立文件夾。
  • Files.delete():刪除一個文件或目錄。
  • Files.copy():複製文件。
  • Files.move():移動文件。
  • Files.size():查看文件個數。
  • Files.read():讀取文件。
  • Files.write():寫入文件。
相關文章
相關標籤/搜索