JAVA基礎(一)

1.JDK   JRE  JVM 三者之間的聯繫與區別

JDK: 顧名思義它是給開發者提供的開發工具箱,是給程序開發者用的。它除了包括完整的JRE(Java Runtime Environment),Java運行環境,還包含了其他供開發者使用的工具包。

JRE: 普通用戶而只需要安裝 JRE(Java Runtime Environment)來運行 Java 程序。而程序開發者必須安裝JDK來編譯、調試程序。

JVM: 當我們運行一個程序時,JVM 負責將字節碼(.class)轉換爲特定機器代碼,JVM 提供了內存管理/垃圾回收和安全機制等。這種獨立於硬件和操作系統,正是 java 程序可以一次編寫多處執行的原因。

區別與聯繫:

    JDK 用於開發,JRE 用於運行java程序 ;

    JDK 和 JRE 中都包含 JVM ;

   JVM 是 java 編程語言的核心並且具有平臺獨立性。

Java 源代碼---->編譯器---->jvm 可執行的 Java 字節碼(.class文件)---->jvm---->jvm 中解釋器----->機器可執行的二進制機器碼---->程序運行。

 

2.構造器 Constructor 是否可被 override

在講繼承的時候我們就知道父類的私有屬性和構造方法並不能被繼承,所以 Constructor 也就不能被 override(重寫),但是可以 overload(重載),所以你可以看到一個類中有多個構造函數的情況。

 

3.重載和重寫的區別

重載: 發生在同一個類中,方法名必須相同,參數類型不同、個數不同、順序不同,方法返回值和訪問修飾符可以不同,發生在編譯時。

重寫: 發生在父子類中,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類;如果父類方法訪問修飾符爲 private 則子類就不能重寫該方法。

 

4.Java 面向對象編程三大特性:封裝、繼承、多態

封裝

封裝把一個對象的屬性私有化,同時提供一些可以被外界訪問的屬性的方法,如果屬性不想被外界訪問,我們大可不必提供方法給外界訪問。但是如果一個類沒有提供給外界訪問的方法,那麼這個類也沒有什麼意義了。

繼承

繼承是使用已存在的類的定義作爲基礎建立新類的技術,新類的定義可以增加新的數據或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。通過使用繼承我們能夠非常方便地複用以前的代碼。

關於繼承如下 3 點請記住:

   1. 子類擁有父類非 private 的屬性和方法。

   2. 子類可以擁有自己屬性和方法,即子類可以對父類進行擴展。

   3. 子類可以用自己的方式實現父類的方法。(重寫)。

多態

所謂多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變量倒底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。

在Java中有兩種形式可以實現多態:繼承(多個子類對同一方法的重寫)和接口(實現接口並覆蓋接口中同一方法)。

 

5.String 和 StringBuffer、StringBuilder 的區別是什麼 String 爲什麼是不可變的

可變性

簡單的來說:String 類中使用 final 關鍵字字符數組保存字符串,private final char value[],所以 String 對象是不可變的。而StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字符數組保存字符串char[]value 但是沒有用 final 關鍵字修飾,所以這兩種對象都是可變的。

StringBuilder 與 StringBuffer 的構造方法都是調用父類構造方法也就是 AbstractStringBuilder 實現的,大家可以自行查閱源碼。

線程安全性

String 中的對象是不可變的,也就可以理解爲常量,線程安全。AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類,定義了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的。StringBuilder 並沒有對方法進行加同步鎖,所以是非線程安全的。   

性能

每次對 String 類型進行改變的時候,都會生成一個新的 String 對象,然後將指針指向新的 String 對象。StringBuffer 每次都會對 StringBuffer 對象本身進行操作,而不是生成新的對象並改變對象引用。相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。

對於三者使用的總結:

    操作少量的數據 = String

    單線程操作字符串緩衝區下操作大量數據 = StringBuilder

    多線程操作字符串緩衝區下操作大量數據 = StringBuffer

 

6.接口和抽象類的區別是什麼

    (1)接口的方法默認是 public,所有方法在接口中不能有實現(Java 8 開始接口方法可以有默認實現),抽象類可以有非抽象的方法
    (2)接口中的實例變量默認是 final 類型的,而抽象類中則不一定
    (3)一個類可以實現多個接口,但最多隻能實現一個抽象類
    (4)一個類實現接口的話要實現接口的所有方法,而抽象類不一定
    (5)接口不能用 new 實例化,但可以聲明,但是必須引用一個實現該接口的對象 從設計層面來說,抽象是對類的抽象,是一種模板設計,接口是行爲的抽象,是一種行爲的規範。

 

7. == 與 equals(重要)

== : 它的作用是判斷兩個對象的地址是不是相等。即,判斷兩個對象是不是同一個對象。(基本數據類型==比較的是值,引用數據類型==比較的是內存地址)

equals() : 它的作用也是判斷兩個對象是否相等。但它一般有兩種使用情況:

    情況1:類沒有覆蓋 equals() 方法。則通過 equals() 比較該類的兩個對象時,等價於通過“==”比較這兩個對象。

    情況2:類覆蓋了 equals() 方法。一般,我們都覆蓋 equals() 方法來兩個對象的內容相等;若它們的內容相等,則返回 true (即,認爲這兩個對象相等)。

 

8.hashCode 與 equals(重要)

hashCode()介紹

hashCode() 的作用是獲取哈希碼,也稱爲散列碼;它實際上是返回一個int整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode() 定義在JDK的Object.java中,這就意味着Java中的任何類都包含有hashCode() 函數。

散列表存儲的是鍵值對(key-value),它的特點是:能根據“鍵”快速的檢索出對應的“值”。這其中就利用到了散列碼!(可以快速找到所需要的對象)

爲什麼要有 hashCode

我們以“HashSet 如何檢查重複”爲例子來說明爲什麼要有 hashCode:

當你把對象加入 HashSet 時,HashSet 會先計算對象的 hashcode 值來判斷對象加入的位置,同時也會與其他已經加入的對象的 hashcode 值作比較,如果沒有相符的hashcode,HashSet會假設對象沒有重複出現。但是如果發現有相同 hashcode 值的對象,這時會調用 equals()方法來檢查 hashcode 相等的對象是否真的相同。如果兩者相同,HashSet 就不會讓其加入操作成功。如果不同的話,就會重新散列到其他位置。這樣我們就大大減少了 equals 的次數,相應就大大提高了執行速度。

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

    1.如果兩個對象相等,則hashcode一定也是相同的

    2.兩個對象相等,對兩個對象分別調用equals方法都返回true

    3.兩個對象有相同的hashcode值,它們也不一定是相等的

    4.因此,equals 方法被覆蓋過,則 hashCode 方法也必須被覆蓋

    5.hashCode() 的默認行爲是對堆上的對象產生獨特值。如果沒有重寫 hashCode(),則該 class 的兩個對象無論如何都不會相等(即使這兩個對象指向相同的數據)

 

Object類默認的hashcode方法

通過將該對象的內部地址轉換成一個整數來實現的(native方法 使用c++實現 jvm源碼)

 

默認的equals方法

public boolean equals(Object obj) {
    return (this == obj);
}

 

爲什麼重寫equals還要重寫hashcode?

例:

    Student s1=new Student("小明",18);

    Student s2=new Student("小明",18);

假如只重寫equals而不重寫hashcode,那麼Student類的hashcode方法就是Object默認的hashcode方法,由於默認的hashcode方法是根據對象的內存地址經哈希算法得來的,顯然此時s1!=s2,故兩者的hashcode不一定相等。

然而重寫了equals,且s1.equals(s2)返回true,根據hashcode的規則,兩個對象相等其哈希值一定相等,所以矛盾就產生了,因此重寫equals一定要重寫hashcode,
 

 

爲什麼兩個對象有相同的hashcode值,它們也不一定是相等的?

在這裏解釋一位小夥伴的問題。以下內容摘自《Head Fisrt Java》。

因爲hashCode() 所使用的雜湊算法也許剛好會讓多個對象傳回相同的雜湊值。越糟糕的雜湊算法越容易碰撞,但這也與數據值域分佈的特性有關(所謂碰撞也就是指的是不同的對象得到相同的 hashCode)。

我們剛剛也提到了 HashSet,如果 HashSet 在對比的時候,同樣的 hashcode 有多個對象,它會使用 equals() 來判斷是否真的相同。也就是說 hashcode 只是用來縮小查找成本。

 

9.Java 中只有值傳遞

(1).對於基本數據類型的傳遞,是進行拷貝,傳遞拷貝出來的副本,不能改變原始的值

(2) 對於對象引用的傳遞,是對引用進行拷貝,傳遞拷貝的引用副本,指向堆中的對象,可以改變對象的值。

 

10 final關鍵字主要用在三個地方:變量、方法、類。

   (1)對於一個final變量,如果是基本數據類型的變量,則其數值一旦在初始化之後便不能更改;如果是引用類型的變量,則在對其初始化之後便不能再讓其指向另一個對象。

    (2)當用final修飾一個類時,表明這個類不能被繼承。final類中的所有成員方法都會被隱式地指定爲final方法。

 

11  static 關鍵字主要有以下四種使用場景:

    (1).修飾成員變量和成員方法: 被 static 修飾的成員屬於類,不屬於單個這個類的某個對象,被類中所有對象共享,可以並且建議通過類名調用。被static 聲明的成員變量屬於靜態成員變量,靜態變量 存放在 Java 內存區域的方法區。調用格式:類名.靜態變量名 類名.靜態方法名()

    (2)靜態代碼塊: 靜態代碼塊定義在類中方法外, 靜態代碼塊在非靜態代碼塊之前執行(靜態代碼塊—>非靜態代碼塊—>構造方法)。 該類不管創建多少對象,靜態代碼塊只執行一次.

    (3)靜態內部類(static修飾類的話只能修飾內部類): 靜態內部類與非靜態內部類之間存在一個最大的區別: 非靜態內部類在編譯完成之後會隱含地保存着一個引用,該引用是指向創建它的外圍類,但是靜態內部類卻沒有。沒有這個引用就意味着:1. 它的創建是不需要依賴外圍類的創建。2. 它不能使用任何外圍類的非static成員變量和方法。

    (4)靜態導包(用來導入類中的靜態資源,1.5之後的新特性): 格式爲:import static 這兩個關鍵字連用可以指定導入某個類中的指定靜態資源,並且不需要使用類名調用類中靜態成員,可以直接使用類中靜態成員變量和成員方法。

 

12 Excption與Error區別

Error表示系統級的錯誤和程序不必處理的異常,是不是不可能恢復,但很困難的情況下的一種嚴重問題;比如內存溢出,不可能指望程序能處理這樣的狀況Exception表示需要捕捉或者需要程序進行處理的異常,是一種設計或實現問題;也就是說,通過程序的修改可以避免或減少這種異常

 

13  java程序執行順序

      (1-3:類加載過程,不涉及構造方法,靜態部分僅加載一次)

      (1-5: 實例化過程,涉及構造方法)

1.類中所有屬性的默認值(一舉而成,類加載時,JVM設置初始值)

2.父類靜態屬性初始化,靜態塊,靜態方法的聲明(按出現順序執行)

3.子類靜態屬性初始化,靜態塊,靜態方法的聲明 (按出現順序執行)(--類加載過程完成--)

4.調用父類的構造方法,

           首先父類的非靜態成員初始化,構造塊,普通方法的聲明(按出現順序執行)

           然後父類構造方法

5.調用子類的構造方法,

         首先子類的非靜態成員初始化,構造塊,普通方法的聲明(按出現順序執行)

         然後子類構造方法

(注意:類加載過程中,可能調用了實例化過程(因爲static可以修飾方法,屬性,代碼塊,內部類),此時則會暫停類加載過程而先執行實例化過程(被打斷),執行結束再進行類加載過程。

https://www.cnblogs.com/greatfish/p/5771548.html(必看)

 

引用:

https://github.com/Snailclimb/JavaGuide

         

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