程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 瘋狂Java講義 讀書筆記(一),java講義讀書筆記

瘋狂Java講義 讀書筆記(一),java講義讀書筆記

編輯:JAVA綜合教程

瘋狂Java講義 讀書筆記(一),java講義讀書筆記


李剛老師的《瘋狂Java講義》(第三版)是我的啟蒙作品,前前後後一共看了3遍,每次都有新的認識。

接下來的一段時間就將一些經典的知識記錄下來。

1.計算機高級語言的執行方式分為編譯型和解釋型,前者運行高效但不能跨平台(C,C++,Object-C),後台可以跨平台但效率不高(Ruby,Python)。Java比較特殊,先編譯生成.class,再在JVM中解釋。

2.垃圾回收機制:依靠垃圾回收算法,何時回收對Java程序員而言具有透明性,因此要養成良好的習慣——對於不需要的對象,不要引用他們。(在堆中進行回收)

3.Java是強類型語言:所有類變量必須先聲明後使用,指定類型的變量只能接受與類型相匹配的值。

4.Java支持兩種類型:1、基本類型:布爾類型、數值類型 2.引用類型:類、接口、數組。

5.強制類型轉化:造成溢出時,之前一直覺得19.745會變成19(實在汗顏),其實是轉換成二進制後再進行截取。

6.常量池:在編譯期被確定,並已被保存在.class文件中的一些數據。包括類、方法、接口中的常量,也包括字符串常量。

7.switch語句:控制表達式的數據類型只能是byte,short,char,int,枚舉,String.

8.break和continue可以通過標簽跳到指定的循環層

public class BreakTest2
{
    public static void main(String[] args)
    {
        outer:
        for (int i = 0 ; i < 5 ; i++ )
        {
            for (int j = 0; j < 3 ; j++ )
            {
                System.out.println("i的值為:" + i + "  j的值為:" + j);
                if (j == 1)
                {
                    break outer;
                }
            }
        }
    }
}

9.棧和堆:1、當一個方法執行時,每個方法都會建立自己的內存棧,在這個方法內定義的變量將會逐個放入這塊棧內存裡,隨著方法的執行結束,這個方法的內存棧也將自動銷毀。因此,所有在方法中定義的局部變量都是放在棧內存中;2、當我們在程序中創建一個對象是,這個對象將被保存到運行是數據區中,以便反復利用,這個運行是數據區就是堆內存。堆內存中的對象不會因方法結束而銷毀,就算方法結束後,這個對象還可能被另一個變量所引用,則這個對象不會銷毀,只有當一個變量沒有任何引用變量引用它,那麼系統的垃圾回收器才會在合適的時候回收它;

10.Arrays:Java8增加的工具類,在java.util包下,支持並發編程

        // 定義一個a數組
        int[] a = new int[]{3, 4 , 5, 6};
        // 定義一個a2數組
        int[] a2 = new int[]{3, 4 , 5, 6};
        // a數組和a2數組的長度相等,每個元素依次相等,將輸出true
        System.out.println("a數組和a2數組是否相等:"
            + Arrays.equals(a , a2));
        // 通過復制a數組,生成一個新的b數組
        int[] b = Arrays.copyOf(a, 6);
        System.out.println("a數組和b數組是否相等:"
            + Arrays.equals(a , b));
        // 輸出b數組的元素,將輸出[3, 4, 5, 6, 0, 0]
        System.out.println("b數組的元素為:"
            + Arrays.toString(b));
        // 將b數組的第3個元素(包括)到第5個元素(不包括)賦為1
        Arrays.fill(b , 2, 4 , 1);
        // 輸出b數組的元素,將輸出[3, 4, 1, 1, 0, 0]
        System.out.println("b數組的元素為:"
            + Arrays.toString(b));
        // 對b數組進行排序
        Arrays.sort(b);
        // 輸出b數組的元素,將輸出[0, 0, 1, 1, 3, 4]
        System.out.println("b數組的元素為:"
            + Arrays.toString(b));
    }

11.Java語言通過new關鍵字調用構造器。

12.this關鍵字:1、讓類中的一個方法,訪問該類裡的另一個方法或者實例變量。2、this所代表的對象是不確定的,但他的類是確定的。3、在構造器中,this代表該構造器正在初始化的對象。4、如果在某個方法中把this作為返回值,則可以多次連續調用同一個方法。

public class ReturnThis
{
    public int age;
    public ReturnThis grow()
    {
        age++;
        // return this返回調用該方法的對象
        return this;
    }
    public static void main(String[] args)
    {
        ReturnThis rt = new ReturnThis();
        // 可以連續調用同一個方法
        rt.grow()
            .grow()
            .grow();
        System.out.println("rt的age成員變量值是:" + rt.age);
    }
}

13.static:不要使用對象去調用static修飾的成員變量,要使用類去調用。

14.值傳遞:將實際參數的副本傳入方法內,參數本身不會受到任何影響。

15.形參可變的方法:定義方法時,在最後一個形參的類型後增加三個點(...)。多個參數值被當成數組傳入。與傳入數組相比,形參可變更加簡潔,但一個方法只能有一個可變形參。

public class Varargs
{
    // 定義了形參個數可變的方法
    public static void test(int a , String... books)
    {
        // books被當成數組處理
        for (String tmp : books)
        {
            System.out.println(tmp);
        }
        // 輸出整數變量a的值
        System.out.println(a);
    }
    public static void main(String[] args)
    {
        // 調用test方法
        test(5 , "瘋狂Java講義" , "輕量級Java EE企業應用實戰");
    }
}

16.遞歸算法:一個方法調用自身,一定要向已知方向遞歸。

17.局部變量:形參(方法簽名中定義的變量),方法局部變量(在方法內定義),代碼塊局部變量(在代碼塊內定義),局部變量不屬於任何類或者實例,它總是保存在其所在方法的棧內存中。

18.封裝:類的成員變量不直接暴露,而是通過方法實現操作和訪問,以便於在方法中添加一些限制條件

19.高內聚:盡可能把模塊的內部數據、功能實現細節隱藏在模塊內部獨立完成,不允許外部直接干預;低耦合:僅暴露少量的方法給外部使用。

20.靜態導入:JDK1.5增加的導包方法,用於導入包內的靜態成員 import static package...

21.構造器:1、構造器是創建Java對象的重要途徑,但這個對象並不是完全由構造器負責創建的。2、子類的構造器必定會調用其父類的構造器(沒有super和this時默認調用無參的構造器)。

22.方法重寫(覆蓋)原則:1、兩同:方法名、參數列表相同 2、兩小:子類方法返回值<=父類方法返回值 3、一大:子類方法訪問權限>=父類方法訪問權限

23.當程序創建一個子類對象時,系統不僅會為該類中定義的實例變量分配內存,也會為它從父類繼承得到的所有實例變量分配內存。

24.引用變量類型:1、編譯時類型:由聲明該變量時使用的類型決定 2、運行時類型:由實際賦給該變量的對象決定 3、編譯時類型和運行時類型不同時,就出現了所謂的多態 4、引用變量在編譯階段只能調用其編譯時類型所具有的方法,但運行時則執行它運行時類型所具有的方法(可用強制類型轉換解決問題)。

25.向上轉型:把一個子類對象直接賦值給父類引用變量;強制類型轉換:把一個父類對象賦給子類引用變量

26多態:1、相同類型的變量,調用同一個方法時呈現出多種不同的行為特征叫做多態 2、成員變量不存在多態,總是調用父類的值

27.instanceof:判斷前面的對象是否是後面的類,或者其子類、實現類的實例

String str="str";
//true
System.out.println(str instanceof Object);
Object obj=new Object();
//false
System.out.println(obj instanceof String);

28.繼承與組合:1繼承代表"is a",組合代表"has a" 2.創建子類對象,系統會為其父類所定義的實例變量分配內存空間,因此繼承和組合在系統開銷上沒有太大的區別

29.初始化塊:1.初始化塊在構造器之前執行(編譯後初始化塊的內容會還原到構造器中) 2.靜態初始化塊在普通初始化塊之前執行

30.包裝類:包裝類的實例可以與數值類型直接比較

31.toString:自定義類時,盡量重寫類的toString方法,便於輸出實例的值

32.==與equals:1.對於引用類型,只有二者指向同一個對象,==才會等於true  2.String類型情況如下,編譯時確定的數據在常量池中,運行時生成的數據在堆內存中

    // s1直接引用常量池中的"瘋狂Java"
        String s1 = "瘋狂Java";
        String s2 = "瘋狂";
        String s3 = "Java";
        // s4後面的字符串值可以在編譯時就確定下來
        // s4直接引用常量池中的"瘋狂Java"
        String s4 = "瘋狂" + "Java";
        // s5後面的字符串值可以在編譯時就確定下來
        // s5直接引用常量池中的"瘋狂Java"
        String s5 = "瘋" + "狂" + "Java";
        // s6後面的字符串值不能在編譯時就確定下來,
        // 不能引用常量池中的字符串
        String s6 = s2 + s3;
        // 使用new調用構造器將會創建一個新的String對象,
        // s7引用堆內存中新創建的String對象
        String s7 = new String("瘋狂Java");
        System.out.println(s1 == s4); // 輸出true
        System.out.println(s1 == s5); // 輸出true
        System.out.println(s1 == s6); // 輸出false
        System.out.println(s1 == s7); // 輸出false

33.重寫equals的條件:1.自反性:x.equals(x)=true 2.對稱性:若x.equals(y)=true,則y.equals(x)=true 3.傳遞性:若x.equals(y)=true,y.equals(z)=true,則x.equals(z)=true 4.一致性:只要x.equals(y)=true且x,y不變,無論調用多少次結果都不變 5.對任何不適Null的x,x.equals(null)=false 6.equals相同,則hashcode相同

34.null類型的實例可以訪問類的靜態方法和靜態變量,在底層是通過該實例的類去訪問的

35.final:1.final變量不是不能被賦值,而是不能被改變 2.final變量必須由程序員顯示的指定初始值 3.final修飾引用變量時,引用地址不可以改變,對象可以改變 4.final修飾的方式不能被重寫,但是可以被重載

36.宏變量:定義final變量時就為該變量指定了初始值,而且可以在編譯時就確定下來,編譯器會把程序中所有用到改變量的地方直接替換成該變量的值(進入常量池)

37.不可變類:1.private final修飾所有成員變量 2.只有getter沒有setter

38.緩存池:先進先出緩存實例,重寫了equals和hsahcode

class CacheImmutale
{
    private static int MAX_SIZE = 10;
    // 使用數組來緩存已有的實例
    private static CacheImmutale[] cache
        = new CacheImmutale[MAX_SIZE];
    // 記錄緩存實例在緩存中的位置,cache[pos-1]是最新緩存的實例
    private static int pos = 0;
    private final String name;
    private CacheImmutale(String name)
    {
        this.name = name;
    }
    public String getName()
    {
        return name;
    }
    public static CacheImmutale valueOf(String name)
    {
        // 遍歷已緩存的對象,
        for (int i = 0 ; i < MAX_SIZE; i++)
        {
            // 如果已有相同實例,直接返回該緩存的實例
            if (cache[i] != null
                && cache[i].getName().equals(name))
            {
                return cache[i];
            }
        }
        // 如果緩存池已滿
        if (pos == MAX_SIZE)
        {
            // 把緩存的第一個對象覆蓋,即把剛剛生成的對象放在緩存池的最開始位置。
            cache[0] = new CacheImmutale(name);
            // 把pos設為1
            pos = 1;
        }
        else
        {
            // 把新創建的對象緩存起來,pos加1
            cache[pos++] = new CacheImmutale(name);
        }
        return cache[pos - 1];

    }
    public boolean equals(Object obj)
    {
        if(this == obj)
        {
            return true;
        }
        if (obj != null && obj.getClass() == CacheImmutale.class)
        {
            CacheImmutale ci = (CacheImmutale)obj;
            return name.equals(ci.getName());
        }
        return false;
    }
    public int hashCode()
    {
        return name.hashCode();
    }
}
public class CacheImmutaleTest
{
    public static void main(String[] args)
    {
        CacheImmutale c1 = CacheImmutale.valueOf("hello");
        CacheImmutale c2 = CacheImmutale.valueOf("hello");
        // 下面代碼將輸出true
        System.out.println(c1 == c2);
    }
}

39.默認方法:1.JDK1.8後新增的方法,在接口中一共有三種方法,抽象方法(abstract),類方法(static),默認方法(default),後兩者必須有方法實現 2.使用接口的實例來調用默認方法

40.抽象類:抽象類作為多個子類的抽象父類,可以被當成系統實現過程的中間產品,這個中間產品已經實現了系統的部分功能,但這個產品依然不能當成最終產品,必須由進一步的完善,

41.內部類:1.提供更好的封裝 2.內部類成員可以直接訪問外部類的私有數據 3.匿名內部類適用於創建只需要一次使用的類 4.局部內部類和匿名內部類不是類成員 5.包含內部類的類被稱為外部類

42.非靜態內部類:1.非靜態內部類對象裡保存了一個外部類的引用 2.外部類對象訪問非靜態內部類成員時,可能非靜態普通內部類對象根本不存在 3.不允許在非靜態內部類定義靜態成員

43.靜態內部類:1.靜態內部類可以包含靜態成員和非靜態成員 2.靜態內部類是外部類的類相關,靜態內部類對象寄生在外部類的類本身中,只持有外部類的類引用,沒有外部類的對象引用

44.內部類的使用: 1.盡量使用靜態內部類(調用簡單)2.局部內部類沒有什麼卵用  3.非靜態內部類的構造器必須由其外部類的對象來調用

public class SubClass extends Out.In
{
    //顯示定義SubClass的構造器
    public SubClass(Out out)
    {
        //通過傳入的Out對象顯式調用In的構造器
        out.super("hello");
    }
}

45.匿名內部類:1.必須繼承一個父類或者實現一個接口 2.不能是抽象類 3.不能定義構造器 4.JDK1.8以前被匿名內部類訪問的局部變量必須使用final修飾,1.8以後會自動加上final修飾

46.枚舉類:可以使用枚舉類來替代靜態final常量

public class Enum {
public enum Season{
    spring,summer,fall,winter;
}
public static void main(String[] args) {
    Season season=Season.spring;
    System.out.println(season);
    switch (season){
    case spring:
        System.out.println("spring");
        break;
    case summer:
        System.out.println("summer");
        break;
    case fall:
        System.out.println("fall");
        break;
    case winter:
        System.out.println("winter");
        break;
    }
    
}

47.垃圾回收:1.只負責回收對象,不負責物理資源 2.程序無法精確控制垃圾回收的運行 3.在回收對象前,會調用對象的finalize方法嘗試讓其獲得新的引用以復活 4.finalize方法何時被調用具有不確定性

public class FinalizeTest
{
    private static FinalizeTest ft = null;
    public void info()
    {
        System.out.println("測試資源清理的finalize方法");
    }
    public static void main(String[] args) throws Exception
    {
        // 創建FinalizeTest對象立即進入可恢復狀態
        new FinalizeTest();
        // 通知系統進行資源回收
//        System.gc();  //①
        // 強制垃圾回收機制調用可恢復對象的finalize()方法
//        Runtime.getRuntime().runFinalization();   //②
        System.runFinalization();   //③
        ft.info();
    }
    public void finalize()
    {
        // 讓tf引用到試圖回收的可恢復對象,即可恢復對象重新變成可達
        ft = this;
    }
}

48.引用類型:1.強引用(最常見的引用) 2.軟引用(當系統內存空間不夠時會被回收) 3.弱引用(比軟引用級別更低,當系統垃圾回收機制運行時,無論內存夠不夠都會被回收) 4.虛引用(沒什麼用)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved