Java基礎總結(一)

Java基礎

switch能否用string做參數

在 Java 7之前,switch 只能支持 byte、short、char、int或者其對應的封裝類以及 Enum 類型。在 Java 7中,String支持被加上了。這個新特性是在編譯器這個層次上實現的。而在Java虛擬機和字節碼這個層次上還是隻支持在switch語句中使用與整數類型兼容的類型。這麼做的目的就是爲了減少這個特性所影響的範圍,以降低實現的代價。

object有哪些公用方法:equals,hashcode,clone,wait,notify、getClass等

  1. clone方法
    保護方法,實現對象的淺複製,只有實現了Cloneable接口纔可以調用該方法,否則拋出CloneNotSupportedException異常。主要是JAVA裏除了8種基本類型傳參數是值傳遞,其他的類對象傳參數都是引用傳遞(說法不準確,java都是值傳遞),我們有時候不希望在方法裏講參數改變,這是就需要在類中複寫clone方法。

  2. getClass方法
    final方法,獲得運行時類型。

  3. toString方法
    該方法用得比較多,一般子類都有覆蓋。

  4. finalize方法
    該方法用於釋放資源。因爲無法確定該方法什麼時候被調用,很少使用。

  5. equals方法
    該方法是非常重要的一個方法。一般equals和==是不一樣的,但是在Object中兩者是一樣的。子類一般都要重寫這個方法。

  6. hashCode方法
    該方法用於哈希查找,可以減少在查找中使用equals的次數,重寫了equals方法一般都要重寫hashCode方法。這個方法在一些具有哈希功能的Collection中用到。一般必須滿足obj1.equals(obj2)==true。可以推出obj1.hashCode()==obj2.hashCode(),但是hashCode相等不一定就滿足equals。不過爲了提高效率,應該儘量使上面兩個條件接近等價。如果不重寫hashcode(),在HashSet中添加兩個equals的對象,會將兩個對象都加入進去。

  7. wait方法
    wait方法就是使當前線程等待該對象的鎖,當前線程必須是該對象的擁有者,也就是具有該對象的鎖。wait()方法一直等待,直到獲得鎖或者被中斷。wait(long timeout)設定一個超時間隔,如果在規定時間內沒有獲得鎖就返回。調用該方法後當前線程進入睡眠狀態,直到以下事件發生。
    (1)其他線程調用了該對象的notify方法。
    (2)其他線程調用了該對象的notifyAll方法。
    (3)其他線程調用了interrupt中斷該線程。
    (4)時間間隔到了。
    此時該線程就可以被調度了,如果是被中斷的話就拋出一個InterruptedException異常。

  8. notify方法
    該方法喚醒在該對象上等待的某個線程。

  9. notifyAll方法
    該方法喚醒在該對象上等待的所有線程。

    • note:7、8、9可以用於多線程通信。
String、StringBuffer與StringBuilder的區別。

String 字符串常量
StringBuilder 字符串變量(非線程安全)
StringBuffer 字符串變量(線程安全)
效率問題以及鎖的問題?
爲什麼效率高?
加鎖加載了哪?

try catch finally,try裏有return,finally還執行麼?

結論:
1. 不管有木有出現異常,finally塊中代碼都會執行;
2. 當try和catch中有return時,finally仍然會執行;
3. finally中有return,返回的值是finally中的值;finally中沒有return,返回的是第一次出現return中的值。

Excption與Error包結構。

https://img-my.csdn.net/uploads/201310/29/1383051170_4167.jpeg

  • 粉紅色的是受檢查的異常(checked exceptions),其必須被 try{}catch語句塊所捕獲,或者在方法簽名裏通過throws子句聲明。
  • 受檢查的異常必須在編譯時被捕捉處理,命名爲 CHecked Exception 是因爲Java編譯器要進行檢查,Java虛擬機也要進行檢查,以確保這個規則得到遵守。
  • 綠色的異常是運行時異常(runtime exceptions),需要程序員自己分析代碼決定是否捕獲和處理,比如 空指針,被0除…。
  • 而聲明爲Error的,則屬於嚴重錯誤,需要根據業務信息進行特殊處理,Error不需要捕捉。

Override和Overload的含義與區別

  • 方法的重寫(Overriding)和重載(Overloading)是Java多態性的不同表現。
  • 重寫(Overriding)是父類與子類之間多態性的一種表現,而重載(Overloading)是一個類中多態性的一種表現。
  • 如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding) 。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同屏蔽了。
  • 如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型或有不同的參數次序,則稱爲方法的重載(Overloading)。不能通過訪問權限、返回類型、拋出的異常進行重載。

  • Override 特點

    1. 覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配,才能達到覆蓋的效果;
    2. 覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
    3. 覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;
    4. 方法被定義爲final不能被重寫。
    5. 對於繼承來說,如果某一方法在父類中是訪問權限是private,那麼就不能在子類對其進行重寫覆蓋,如果定義的話,也只是定義了一個新方法,而不會達到重寫覆蓋的效果。(通常存在於父類和子類之間。)
  • Overload 特點

    1. 在使用重載時只能通過不同的參數樣式。例如,不同的參數類型,不同的參數個數,不同的參數順序;
    2. 不能通過訪問權限、返回類型、拋出的異常進行重載;
    3. 方法的異常類型和數目不會對重載造成影響;
    4. 重載事件通常發生在同一個類中,構造方法或者普通方法。
  • 其具體實現機制:

    • overload是重載,重載是一種參數多態機制,即代碼通過參數的類型或個數不同而實現的多態機制。是一種靜態的綁定機制(在編譯時已經知道具體執行的是哪個代碼段)。
    • override是覆蓋。覆蓋是一種動態綁定的多態機制。即在父類和子類中同名元素(如成員函數)有不同 的實現代碼。執行的是哪個代碼是根據運行時實際情況而定的。

Interface與abstract類的區別

  • 接口和抽象類有什麼區別,選擇使用接口和抽象類的依據是什麼?
    1. 接口和抽象類的概念不一樣。接口是對動作的抽象,抽象類是對根源的抽象。
    2. 抽象類表示的是,這個對象是什麼。接口表示的是,這個對象能做什麼。比如,男人,女人,這兩個類(如果是類的話……),他們的抽象類是人。說明,他們都是人。人可以吃東西,狗也可以吃東西,你可以把“吃東西”定義成一個接口,然後讓這些類去實現它.所以,在高級語言上,一個類只能繼承一個類(抽象類)(正如人不可能同時是生物和非生物),但是可以實現多個接口(吃飯接口、走路接口)。
    3. 第一點, 接口是抽象類的變體,接口中所有的方法都是抽象的。而抽象類是聲明方法的存在而不去實現它的類。
    4. 第二點, 接口可以多繼承,抽象類不行
    5. 第三點, 接口定義方法,不能實現,而抽象類可以實現部分方法。
    6. 第四點, 接口中基本數據類型爲static 而抽類象不是的。
    7. 當你關注一個事物的本質的時候,用抽象類;當你關注一個操作的時候,用接口。
    8. 抽象類的功能要遠超過接口,但是,定義抽象類的代價高。因爲高級語言來說(從實際設計上來說也是)每個類只能繼承一個類。在這個類中,你必須繼承或編寫出其所有子類的
    9. 雖然接口在功能上會弱化許多,但是它只是針對一個動作的描述。而且你可以在一個類中同時實現多個接口。在設計階段會降低難度的。

JDK8新特性
* 在JDK7及以前的版本中,接口中都是抽象方法,不能定義方法體,但是從jdk8開始,接口中可以定義靜態的非抽象的方法,直接使用接口名調用靜態方法,但是它的實現類的類名或者實例卻不可以調用接口中的靜態方法。
* 也可以定義普通的非抽象的方法,普通的非抽象方法要在返回值前加上default,對於普通的非抽象方法必須使用子類的實例來調用。如果有多個接口定義了相同的默認方法,實現多個這些接口時必須重寫默認方法,否則編譯失敗。
* jdk8的接口中,開始允許使用關鍵字default。

面向接口編程與面向對象編程(對上面進行延伸)

  • 面向接口編程就是面向抽象編程、面向規範編程,它帶來的最大的好處便是解耦、增強擴展性、屏蔽變化。
  • 封閉-開放原則:設計最好滿足對修改封閉,對擴展開放。爲什麼?上一個版本代碼已經發布,你新添加的業務要去修改原有的代碼,會引入很多未知的bug,儘量不動原有代碼,減少bug出現的概率;而是以“添加”的形式增加新功能。
    1. 實現多態。
    2. 減少耦合性。
    3. 令各個成員依賴與抽象, 而不是依賴與具體。
    4. 方便維護和擴展。

@see:http://blog.csdn.net/nvd11/article/details/42305895

static class 與non static class的區別
  • 內部靜態類不需要有指向外部類的引用;但非靜態內部類需要持有對外部類的引用。
  • 非靜態內部類能夠訪問外部類的靜態和非靜態成員;靜態類不能訪問外部類的非靜態成員,他只能訪問外部類的靜態成員。
  • 一個非靜態內部類不能脫離外部類實體被創建,一個非靜態內部類可以訪問外部類的數據和方法,因爲他就在外部類裏面。

【關於內存泄露】
* 內部類持有外部類的引用,或者說內部類對外部類持有隱式的引用。假如我們在內部類中做耗時的操作或者說有個while(true)死循環,即內部類的對象一直存在; 那麼當這個MainActivity應該被回收時(比如屏幕的旋轉)GC發現它還被其內部類的對象引用 所以就不會將其回收.假如該Activity中含有大量的資源(比如圖片)那麼就很容易發生OOM.
* 優化方式:使用靜態的內部類,這樣的內部類就不會持有外部類的隱式引用,也就不會影響到GC對於外部類的回收;使用弱引用對耗內存對象進行包裝。

        public class A {
        void a1() {

        }
        class B{
            void b1() {
                // 可以直接訪問
                a1();
            }
        }

        static class C {
            void c1() {
                // 不能訪問
                // a1();
            }
        }

        public static void main(String[] args) {
            A a = new A();
            // 非靜態內部類必須依附於外部類
            B b = a.new B();
            C c = new C();
        }
    }

foreach與正常for循環效率對比。

  • 需要循環數組結構的數據時,建議使用普通for循環,因爲for循環採用下標訪問,對於數組結構的數據來說,採用下標訪問比較好。
  • 需要循環鏈表結構的數據時,一定不要使用普通for循環,這種做法很糟糕,數據量大的時候有可能會導致系統崩潰。爲什麼:查看鏈表源碼(比如LinkedList)的get(i)方法發現,會遍歷爲了查詢一個值整個鏈表,直到便利到當前位置;但是數組(比如ArrayList)就不一樣了,直接定位的。
  • for在遍歷期間可以修改;foreach在遍歷期間不可以修改。

  • fail-fast 機制是java集合(Collection)中的一種錯誤機制。當多個線程對同一個集合的內容進行操作時,就可能會產生fail-fast事件。例如:當某一個線程A通過iterator去遍歷某集合的過程中,若該集合的內容被其他線程所改變了;那麼線程A訪問集合時,就會拋出ConcurrentModificationException異常,產生fail-fast事件。

  • 要了解fail-fast機制,我們首先要對ConcurrentModificationException 異常有所瞭解。當方法檢測到對象的併發修改,但不允許這種修改時就拋出該異常。同時需要注意的是,該異常不會始終指出對象已經由不同線程併發修改,如果單線程違反了規則,同樣也有可能會拋出改異常。
  • 誠然,迭代器的快速失敗行爲無法得到保證,它不能保證一定會出現該錯誤,但是快速失敗操作會盡最大努力拋出ConcurrentModificationException異常,所以因此,爲提高此類操作的正確性而編寫一個依賴於此異常的程序是錯誤的做法,正確做法是:ConcurrentModificationException 應該僅用於檢測 bug。

反射機制

  1. 什麼是反射機制?
    簡單說,反射機制得是程序在運行時能夠獲取自身的信息。在java中,只要給定類的名字,那麼就可以通過反射機制來獲得類的所有信息。

  2. java反射機制提供了什麼功能?

    • 在運行時能夠判斷任意一個對象所屬的類
    • 在運行時構造任意一個類的對象
    • 在運行時判斷任意一個類所具有的成員變量和方法
    • 在運行時調用任一對象的方法
    • 在運行時創建新類對象
  3. 哪裏用到反射機制?
    jdbc中有一行代碼:Class.forName(‘com.MySQL.jdbc.Driver.class’).newInstance();那個時候只知道生成驅動對象實例,後來才知道,這就是反射,現在
    很多框架都用到反射機制,hibernate,struts都是用反射機制實現的。

    • note:這也就是爲什麼說使用雙重鎖實現單例模式有風險,可以通過反射創建對象,因此不能保證只有一個實例。

String類內部實現,能否改變String對象內容,String源碼

Java1.7與1.8新特性

  • jdk1.7
    1 對集合類的語言支持;
    2 自動資源管理;
    3 改進的通用實例創建類型推斷;
    4 數字字面量下劃線支持;
    5 switch中使用string;
    6 二進制字面量;
    7 簡化可變參數方法調用;
    8 新增一些取環境信息的工具方法;
    9 Boolean類型反轉,空指針安全,參與位運算;
    10 兩個char間的equals;
    11 安全的加減乘除;
    12 map集合支持併發請求 ,且可以寫成 Map map = {name:”xxx”,age:18};

  • jdk1.8
    接口的默認方法與靜態方法
    lambda表達式
    Annotation 多重註解
    java.util.stream支持在流上的函數式風格的值操作

總結文檔在這裏,比較詳細~https://github.com/scsfwgy/AndroiderTechnology

發佈了65 篇原創文章 · 獲贊 142 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章