Java學習筆記(Java程序設計實用教程4th——葉核亞)

第一天

1. Java命名規範:關鍵字、變量、對象、方法、包等名字通常全部字母小寫,如果是多個單詞構成的話就首字母小寫,後面單詞首字母大寫,比如String類中的toString;類名首字母大寫;常量名全部大寫。

2. 基本數據類型:

**1)數據類型分類:**Java分爲基本類型和引用類型 。其中,基本類型有byte、short、int、long、float、double、char、boolean,它們的變量作爲參數傳遞時只是複製了一份,所以不會改變,比如int a=4;傳到addOne(int a)這個方法執行後a的值還是4。引用類型有數組、類和接口,當它們的變量當做值傳遞的時候就會改變,就像C語言裏面傳遞指針那樣。

2)基本數據類型的取值範圍以及字節數:

我覺得這個寫得很好:Java 基本數據類型取值範圍講解

注意一個:boolean的默認值是false。

3)數組:

  • 數組的聲明:
int a[];//可以這樣
int[] a;//也可以這樣

但是要注意一下,int a[],i;int[] a,i;不一樣的:a都是數組沒問題,但是第一種那裏的i是整型,而第二種那裏的是數組!!!

  • 用於數組的逐元循環的for語句:
  • 比如:
int fib[]=new int[n];
for(int value:fib)//這個就是了
    System.out.println(value);

這裏的value就會依次獲得數組的值。要注意value的類型要和數組的類型一樣。

  • 數組的引用模型:

  • 數組是一個引用類型,所以它傳值給方法之後,方法體裏面是可以改變數組的元素的。來一個對比看看。int a=1,b;先讓b=a;這個之後b=a=1了,然後再調用方法addOne(b);之後,b=1+1=2;但是a還是爲1;再看看數組的:int a[]={1,2,3,4,5},b[];讓b=a(這就是引用賦值了);再b[0]=999;這時候a[0]也變成了999了。就像C++裏面的指針一樣,a,b都指向了同一個數組.

  • 二維數組:
int array[][]=new int[5][6];
System.out.println(array.length);//輸出5,即二維數組的行數
System.out.println(array[0].length);//輸出6,即二位數組的列數
//不規則的二維數組
int arr[][]=new int[3][];//申請了第一維的空間
arr[0]=new int[3];//這裏二維數組的第一行就有3個int空間了
arr[1]=new int[6];//這裏二維數組的第二行就有6個int空間了

4) 參數的傳遞:

  • 基本數據類型—》傳值
  • 引用數據類型—》傳引用
  • 常量形參:
public static void functionA(final int n){
    //聲明n爲常量,方法體裏不能賦值
    n=10;//這樣是錯的,不能對常量賦值
}
public static void functionB(final int arr[]){
    //聲明數組爲常量,在方法體裏面不能更改引用
    arr[0]=10;//可以,更改的是數組元素
    arr = new int[4];//不行,不能對常量賦值,即不能改變數組的引用
}
  • 可變形參:向一個方法傳遞可變數目的元素,除了數組參數,還可以通過可變形參實現。在形參類型後面加”…”就表示改形參數目可變(也就是把它當做一個數組)。但是可變形參只能用在最後一個形參位置,並且一個方法最多只能有一個可變形參。比如:
public static void print(int... value);//可變形式參數,可將value視爲int[]類型  

【注意】在方法重載中,重載方法之間必須以參數列表相區別,不能以返回值相區別!!!因爲在編譯時,編譯器是根據方法實際參數的數據類型、個數和次序來確定執行重載方法的哪一個。


第二天

  1. 對象引用模型:首先看看一個測試代碼
public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Year y1 = new Year(2020, 1, 1);
        y1.print();//輸出是
        Year y2 = y1;
        y2.print();
        y2 = new Year();
        y2.print();
        y2.set(y1);
        y2.print();
    }

}

class Year {
    private int year;
    private int month;
    private int day;

    public Year(int year, int month, int day) {
        super();
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public Year() {
        this.year = 2017;
        this.month = 1;
        this.day = 1;
    }

    public void set(Year y) {
        this.year = y.year;
        this.month = y.month;
        this.day = y.day;
    }
    //也可以是拷貝構造函數,效果同上
//  public Year(Year y){
//      this.year = y.year;
//      this.month = y.month;
//      this.day = y.day;
//  }


    public void print() {
        System.out.println(year + " " + month + " " + day);
    }
}

運行結果:
總結一下:如果兩個對象之間是賦值,如上代碼中的y2=y1,這時候y2是不會開闢空間的,y1和y2指向同一個對象,但是用了new後就會給它開闢空間,y2=new Year();y2就有了自己的地盤了。這就像是C++裏面的一樣,只要有新對象產生就會有空間的開闢。記住,有new就開闢。
嗯,就是這樣(圖一)

**【拓展一下】**return this.year+’-‘+this.month+’-‘+this.day;和
return return this.year+”-“+this.month+”-“+this.day;的區別:前一個返回值是int後一個是String,不信可以試試。

2.對象關係和比較運算(都是boolean):

  • instanceof運算符是判斷一個對象所引用的實例是不是屬於某個類。比如上面的代碼,y1就屬於Year,所以 y1 instanceof Year;就是true咯。

  • 基本數據類型的比較:比如int,float,double等等,都是隻比較兩個變量的值是不是相等。

  • 對象比較:這個又有兩種比較了。第一種就是形如 y1==y2;第二種就是y1.equals(y2)。讓我們回到上面的圖一看看,如果是情況一這樣,那麼兩種方法都是true了,但是情況二中兩個都是false。可以加上這兩行代碼測測。
System.out.println(y1==y2);
System.out.println(y1.equals(y2));

3.靜態成員:

  • 靜態成員屬於類,即使沒有創建實例,也可以通過類名訪問靜態成員變量/方法。在靜態成員方法體中,不能訪問實例成員,不能使用this引用!!!!!!!!

  • 同名的實例方法被覆蓋,同名的靜態方法被隱藏。它們的區別在於:子類對象轉換成父類對象後能夠訪問父類被隱藏的變量和方法,而不能訪問父類被覆蓋的變量和方法。子類如要訪問父類中被隱藏的實例變量,則需要使用super關鍵字;如果要訪問父類中被隱藏的類變量,則需要用父類的名字加“.”來訪問。

還是看個例子好:
//file name:Parent.java

public class Parent {
    protected static String kind = "This is Parent class";// 這是類變量
    protected static int age = 50;// 這是類變量
    protected String name = "Parent"; // 這是實例變量

    /**
     * 靜態方法
     * 
     * @return 返回Parent的kind
     */
    public static String getKind() {
        System.out.print("Parent.getKind():");
        // return this.kind;//錯誤
        return kind;
    }

    /**
     * 靜態方法
     * 
     * @return 返回Parent的age
     */
    public static int getAge() {
        System.out.print("Parent.getAge():");
        return age;// 如果是this.age,錯誤
    }

    /**
     * 實例方法
     * 
     * @return Parent的name
     */
    public String getName() {
        return this.name;
    }

    /**
     * final方法
     * 
     * @return age+1
     */
    public final int nextAge() {
        return ++age;
    }
}

//file name:Child.java

public class Child extends Parent {
    protected static String kind = "This is CHild class";
    protected int age = 25;// 實例變量,這個和Parent中不同
    protected String name = "Child";

    /**
     * 靜態方法,隱藏了Parent中的方法
     * 
     * @return child中的kind
     */
    public static String getKind() {
        System.out.print("Child.getKind():");
        return kind;
    }

    /**
     * 靜態方法
     * 
     * @return 父類的名字
     */
    public static String getParentKind() {
        // 通過父類名加.訪問
        return Parent.kind;
    }

    /**
     * 實例方法
     * 
     * @return Child的name
     */
    public String getName() {
        return this.name;
    }

    /**
     * 實例方法
     * 
     * @return Parent中的name
     */
    public String getParentName() {
        return super.name;
    }

    // //這樣是錯的,因爲實例方法不能覆蓋父類的靜態方法
    // public int getAge(){
    // return this.age;
    // }
    // 這樣也是不行的,父類中的final方法不能夠被覆蓋
    // public int nextAge(){
    // return ++age;
    // }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Child child = new Child();
        System.out.println("child name:" + child.name + ";age:" + child.age + ";kind:" + child.kind);

        Parent parent = child;// 將child類型轉換成Parent對象
        System.out.println("After name:" + parent.name + ";age:" + parent.age + ";kind:" + parent.kind);
        System.out.println();
        System.out.println("child.getParentName():" + child.getParentName());
        System.out.println("child.getParentKind():" + child.getParentKind());

        System.out.println();
        child.getName();
        child.getKind();
        parent.getName();
        parent.getKind();

    }
}

運行結果

分析:


第三天

  • 抽象類:
    • 使用關鍵字abstract聲明的類稱爲抽象類,使用abstract聲明的成員方發稱爲抽象方法。
    • 構造方法、靜態成員方法不能被聲明爲抽象方法。
    • 抽象類中可以有非抽象方法,但是有抽象方法的類一定要聲明爲抽象類。
    • 抽象方法中也有構造方法,而且如果有某個類繼承了該抽象方法,需要給該抽象類提供參數以初始化。
  • 最終類:
    • 使用關鍵字final聲明的類就是最終類。
    • 最終類不能被繼承,即不能有子類。
    • 最終類中包含的都是最終方法;非最終類也可以有最終方法。
    • 最終方法不能被子類覆蓋。
  • 接口:
    • 接口是一種(引用)數據類型
    • 接口中的成員變量都是常量(變量名全部大寫),聲明時必須賦值,默認修飾符爲public static final,不能聲明實例成員變量。
    • 接口中的成員方法都是抽象的實例成員方法,默認修飾符爲public abstract,不能聲明爲static。(特別注意,如果某個類實現某個接口,必須加上public,如圖)
      -
    • 接口不能包含構造方法,因爲構造方法不能是抽象的。
    • 接口的訪問控制權限是public或缺省。
    • 接口可以多重繼承。
    • 一個類可以實現多個接口,多個接口之間用逗號分隔。
    • 一個非抽象類如果聲明實現多個接口,那麼它必須實現(覆蓋)所有指定接口中的所有抽象方法,方法的參數列表必須相同,否則它必須聲明爲抽象類。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章