java學習03day

pwnda發表於2024-11-26

Java的一些特性

變數

java的變數相對於c語言而言不能重複定義會爆錯

int e,f = 30;

上述的程式碼相當於f為30,e沒有進行復制

強型別語言:每個變數都必須宣告其型別

資料型別

資料型別分為:1、基本資料型別:數值型(整數型別(byte、short、int、long)浮點型別(float、double))、字元型(char)、布林型(boolean)

​ 2、引用資料型別:類(class)、介面(interface)、陣列。

在 Java 中,輸出可以以多種形式進行,但最終都是透過字元流或位元組流的方式輸出到控制檯、檔案或其他輸出裝置。以下是一些常見的輸出方式及其特點:

在輸出的時候+先執行加法操作則之後如果是數與數的操作則還是加法操作

如果先是連線操作則下面還是連線操作:

System.out.println("輸出的是"+now);
System.out.println("結果為"+5+6);

在輸出超過int型別的整數的時候則要在數值的最後新增L

long a = 1234567899L;

字串使用float的時候則要在字串的最後新增f:

float now = 3.14f;

方法(函式)

與c++的區別:

  • C++ 函式

    • 函式是獨立的程式碼塊,可以在全域性範圍內定義,也可以定義在類內部(稱為成員函式)。
    • C++ 支援全域性函式和名稱空間中的函式。
  • Java 方法

    • 方法是類的一部分,必須在類內部定義。Java 不支援全域性函式。

    • 方法是物件的行為,通常與物件的狀態(屬性)相關聯。

    • C++ 支援函式過載(同名函式引數不同)和虛擬函式(支援多型,透過基類指標或引用呼叫派生類的方法)。

    • C++ 中的虛擬函式透過 virtual 關鍵字宣告,允許在派生類中重寫。

    • Java 也支援方法過載和方法重寫。重寫的方法必須與父類中的方法具有相同的名稱和引數列表。

    • 在 Java 中,所有的方法預設都是虛擬的,除非使用 finalstatic 關鍵字修飾。

在 Java 中,函式引數不能有預設值,因此你提供的這個程式碼片段是無效的。Java 不支援像 C++ 那樣在方法引數中指定預設值。

java方法的過載:在同一類中的方法名相同,形參列表不同的多個方法構成方法的過載,其中的形參列表可以是型別不同、順序不同、個數不同

陣列

在 Java 中,陣列的定義和初始化是兩個不同的概念,它們的順序和方式與 Java 的記憶體管理和虛擬機器(JVM)的工作機制有關。下面是對這一現象的詳細解釋:

1. 陣列的定義與初始化

  • 定義:在 Java 中,定義陣列是指宣告一個陣列變數,指定其型別和名稱,但並不分配記憶體。

    int[] myArray; // 定義一個整型陣列變數
    
  • 初始化:初始化陣列是指分配記憶體並設定陣列的初始值。可以透過以下方式進行初始化:

    myArray = new int[10]; // 初始化陣列,分配記憶體空間
    

    或者結合定義和初始化:

    int[] myArray = new int[10]; // 定義並初始化陣列
    

2. 虛擬機器與記憶體管理

  • 記憶體分配:在 Java 中,陣列的記憶體分配是由 JVM 管理的。當你使用 new 關鍵字初始化陣列時,JVM 會在堆記憶體中分配相應的空間。JVM 負責管理記憶體的分配和釋放,這與虛擬機器的設計有關。
  • 型別安全:Java 是一種強型別語言,因此在定義陣列時需要指定陣列的型別。這是為了確保在使用陣列時能夠進行型別檢查,避免型別不匹配的錯誤。

3. 為什麼需要先定義再初始化

  • 清晰的語義:透過先定義陣列,程式設計師可以清楚地知道該變數的型別和用途。這有助於程式碼的可讀性和可維護性。
  • 避免空指標異常:在 Java 中,未初始化的陣列變數預設值為 null。在使用陣列之前必須先初始化它,這樣可以減少空指標異常的風險。
  • 記憶體管理:透過分開定義和初始化,可以更靈活地管理記憶體。例如,你可以在條件語句中根據需要來初始化陣列。

4. 總結

陣列在 Java 中需要先定義再初始化的原因與 Java 的記憶體管理、型別安全以及程式碼的可讀性等因素有關。這並不是因為虛擬化的緣故,而是 Java 語言設計的基本原則和 JVM 的記憶體管理機制共同導致的。透過這種方式,Java 提供了更安全和更清晰的程式設計體驗。

陣列的增強輸出:

int[] arr;
arr = new int[4];
int[] now = new int[66];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
System.out.println("陣列的檢視:增強for迴圈方式:");
for(int num:arr){//對arr陣列進行遍歷,遍歷出來的每一個元素用num進行接收
    System.out.println(num);
}

增強for迴圈和正常for迴圈的區別:

1. 用途

  • 增強 for 迴圈
    • 主要用於遍歷集合或陣列,簡化了程式碼,避免了顯式的索引操作。
    • 適合於只需要讀取元素的場景,不適合於需要修改元素的情況。
  • 正常 for 迴圈
    • 更靈活,可以自由控制迴圈的起始位置、終止條件和步進值。
    • 適合於需要修改元素、訪問特定索引或需要複雜邏輯的場景。

2. 可讀性

  • 增強 for 迴圈
    • 更加簡潔和易讀,特別是在處理集合時,程式碼更清晰。
    • 減少了錯誤的可能性,如索引越界等。
  • 正常 for 迴圈
    • 程式碼相對較長,可能會增加出錯的機會,尤其是在複雜的迴圈條件下。

3. 效能

  • 增強 for 迴圈
    • 在大多數情況下,效能與正常 for 迴圈相似,因為它在內部仍然使用迭代器或索引。
    • 但在某些情況下,增強 for 迴圈可能會略微影響效能,特別是在處理大型資料集時。
  • 正常 for 迴圈
    • 由於可以直接使用索引訪問陣列元素,可能在某些情況下表現得更高效,尤其是在陣列操作中。

總結

  • 增強 for 迴圈 更加簡潔和易讀,適合用於遍歷集合或陣列,但不適合需要修改元素或複雜邏輯的情況。

  • 正常 for 迴圈 提供了更多的靈活性,適合需要對索引進行精細控制的場景。

類和物件

類:對物件向上抽取出像的部分、公共的部分一次形成類,類就相當於一個模板

物件:模板下具體的產物可以理解為具體的物件,物件就是一個一個及具體的例項,就相當於這個模板下具體的產品。

java中先定義類,在建立物件

類:

package com.day01.test3;
/*
* 人類
* */
public class Person {
//    特性-屬性-名詞
    String name;
    int age;
    int height;

//    行為-方法-動詞
//    定義一個學習的方法
    public void study(){
        System.out.println("學海無涯苦作舟");
    }
}

物件:

package com.day01.test3;

public class Test {
//    程式的入口(不是大類的程式入口是小類之間的呼叫)
    public static void main(String[] args) {
    //對Person類的物件建立,建立了一個Person物件
        Person p1 = new Person();
        p1.name = "李薇";
        p1.age  = 24;
        p1.height = 180;
        System.out.println(p1.name);
        System.out.println(p1.age);
//        呼叫方法
        p1.study();


    }
}

構造器

對於一個類而言,一般有三種常見的成員:屬性方法、構造器、

這三種成員都可以定義零個或多個。

構造方法(構造器),是一個建立物件時被自動呼叫的特殊方法,用於物件的額初始化。java嘔吐難過new關鍵字來呼叫構造器,從而返回該類的例項。

類:

package com.day01.test3;
/*
* 人類
* */
public class Person {
//    特性-屬性-名詞
    String name;
    int age;
    int height;

//    行為-方法-動詞
//    定義一個學習的方法

    public void study(){
        System.out.println("學海無涯苦作舟");
    }
//  構造器的引數名字,如果和屬性名字重名,就會發生就近原則
//  如果重名,你想要給屬性賦值,那麼就在想要表達屬性的變數前加上this.來修價
    public Person(){
        System.out.println("45天秤神");

    }
    public Person(int age){
        System.out.println("李薇的年齡為" + age);
        this.age = age;
        this.name = "王八蛋";
        this.height = 156;
    }

}

物件的生成:

package com.day01.test3;

public class Test2 {
    public static void main(String[] args) {
        /*
        * 建立一個Persion類的物件
        * 其中的Person是一個空的構造方法
        * new關鍵字對方法進行呼叫 -》構造器的作用:底層就會自動幫我們建立物件之後,進行初始化的操作。
        * 如果一個類沒有顯示編寫構造器的話,那麼系統會為這個類預設分配一個空的構造方法
        * 呼叫構造器以後,對物件進行初始化作,將物件的地址返回給p
        * 以後儘量保證空構造器的存在,以後學到框架,某些框架底層需要空構造器,如果你沒有新增就會報錯。
        * 如果一個類中有構造器,那麼系統就不會幫你分配預設的空構造器
        * */


        Person p = new Person(20);
    }
}

重點特性:

  • 其中的Person是一個空的構造方法

  • new關鍵字對方法進行呼叫 -》構造器的作用:底層就會自動幫我們建立物件之後,進行初始化的操作。

  • 如果一個類沒有顯示編寫構造器的話,那麼系統會為這個類預設分配一個空的構造方法

  • 呼叫構造器以後,對物件進行初始化作,將物件的地址返回給p

  • 以後儘量保證空構造器的存在,以後學到框架,某些框架底層需要空構造器,如果你沒有新增就會報錯。

  • 如果一個類中有構造器,那麼系統就不會幫你分配預設的空構造器

構造方法也是方法,只不過有特殊的作用而已。與普通方法一樣,構造方法也可以過載。(一般都會進行過載一個空的構造方法)

封裝

我們程式設計追求“高內聚,低耦合

高內聚:類的內部資料操作細節自己完成,不允許外部干涉;
低耦合:僅對外暴露少量的方法用於使用。
隱藏物件內部的複雜性,只對外公開簡單的介面。便於外界呼叫,從而提高系
統的可擴充套件性、可維護性,提高程式的安全性。通俗的說,把該隱藏的隱藏起
來,該暴露的暴露出來。這就是封裝性的設計思想。

示例程式碼:

package com.day01.test4;

public class Girl {
    private int age;
    public void shezhiAge(int age){
        if(age>18){
            this.age = 18;
        }else{
            this.age = age;
        }
    }
    public int Age(){
        return this.age;
    }
}
package com.day01.test4;

public class Tets {
    public static void main(String[] args) {
        Girl g = new Girl();
        g.shezhiAge(33);
        System.out.println(g.Age());
    }
}

上述的程式碼就展示了內部高耦合,(透過函式範圍物件內部的資料與直接訪問內部的資料之間的區別),透過函式訪問內部的資料,開發者可以根據自己的意願對物件內部的資料進行限制。

alt+insert:能夠快捷生成get和set方法。

繼承

類是對物件的抽象
繼承是對類的抽象
超類/基類/父類:從眾多的類中在進行抽象出來的公共的類

繼承的格式:子類 extends 父類

繼承的好處:
1.提高了程式碼的複用性
2.便於程式碼的擴充套件
3.為了多型的使用,是多型使用的前提

示例程式碼:

package com.day01.test5;

public class Person {
    //父類中的公共屬性
    private int age;
    private String name;
    private double height;


    //    父類中公共的方法
    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    //吃飯
    public void eat(){
        System.out.println("人類可以吃飯");
    }
    public void sleep(){
        System.out.println("人類可以睡覺");
    }
    public void shout(){
        System.out.println("人類可以喊叫");
    }
}
package com.day01.test5;

public class Student extends Person{//子類student繼承父類Persoin
    //定義子類額外的、擴充套件的方法
    private int sno;

//    定義子類的額外的、擴充套件的方法

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }
//    學習
    public void study(){
        System.out.println("學生可以進行學習");
    }
}
package com.day01.test5;

public class Test {
    public static void main(String[] args) {
        //定義一個子類具體的物件
        Student s = new Student();
        s.setAge(10);
        s.setSno(102030);
        s.setName("雷偉");
        s.setHeight(181.11);
        s.study();
        s.eat();
        s.shout();
        System.out.println(s.getAge());
    }
}

方法的重寫

方法的重寫:
發生在子類和父類中,當子類對父類提供的方法不滿意的時候,
要對父類的方法進行重寫

方法的重寫有嚴格的格式要求:
子類的方法名字和父類必須一致,引數列表(個數,型別,順序)也要和父類一致。

過載和重寫的區別:
過載:在同一個類中,當方法名相同,形參列表不同的時候,多個方法構成了過載
重寫:在不同的類中,子類對父類提供的方法不滿意,對父類的方法進行重寫

多型

多型:通俗來說,就是多種形態,具體點就是去完成某個行為,當不同的物件
去完成時會產生出不同的狀態。同一種行為,不同的子類呈現出來的狀態是不
同的。

pwnda(自己的理解):多型是為了讓一個函式能夠傳入不同的引數(邏輯上的不同的引數)(前提這些執行的方法有著相同的抽象的父類),從而可以在相同的一個方法根據傳入引數的不同執行不同的效果。真正傳入的引數就是兩者共同的父類。(合成的寫法就是用子類來初始化這個父類的物件),

前提在子類中對父類的方法進行了重寫。並且在多型執行的函式中執行的就是重寫的方法

示例程式碼:

抽象的父類:

package com.day01.test7;

public class Animal {
    public void shout(){
        System.out.println("叫!!!!!!");
    }
}

子類:

package com.day01.test7;

public class Dog extends Animal{
//    喊叫
    public void shout(){
        System.out.println("狗-汪汪叫");
    }
    public void guard(){
       System.out.println("汪汪隊立大功");
    }
}

子類:

package com.day01.test7;

public class Cat extends Animal{
    public void shout(){
        System.out.println("貓:喵喵喵叫");
    }
    public void scratch(){
        System.out.println("貓抓人");
    }

}
package com.day01.test7;

public class Test {
    public static void main(String[] args) {
        //    建立女孩的例項、物件:
        Girl now = new Girl();
//    建立貓的例項
//        Cat c = new Cat();
//        Dog d = new Dog();
//        now.play(c);
//        now.play(d);
        Animal an;//定義一個具體的動物
        Cat c = new Cat();//具體的貓
        an = c;//讓動物是一隻具體的貓
//        合成一句話:Animal an = new Cat();
        now.play(an);
    }

}

異常處理

try-catch-finally-throw-throws

異常就是在程式的執行過程中所發生的不正常的事件,它會中斷正在執行的程式。

所需檔案找不到
網路連線不通或中斷
算術運算錯 (被零除...)
陣列下標越界
裝載一個不存在的類或者對null物件操作
型別轉換異常

Java提供異常處理機制。它將異常處理程式碼和和業務程式碼分離,使程式更優雅,更好的
容錯性,高鍵壯性。

Java的異常處理是透過5個關鍵字來實現的:try、catch、finally、throw、throws

程式出錯捕獲之後可以繼續執行後面的程式碼

try-catch執行情況

情況1:try塊中程式碼沒有出現異常
不執行catch塊程式碼,執行catch塊後邊的程式碼
情況2:try塊中程式碼出現異常,catch中異常型別匹配(相同或者父類)
Java會生成相應的異常物件,Java系統尋找匹配的catch塊,執行catch塊程式碼,執行
catch塊後邊的程式碼。try塊中尚未執行的語句不會執行。
情況3:try塊中程式碼出現異常,catch中異常型別不匹配
不執行catch塊程式碼,不執行catch塊後邊的程式碼,程式會中斷執行
catch塊中如何處理異常
其中一種方式:自定義內容輸出

注:exception可以匹配所有的異常(是所有錯誤子類的父類)

示例:

package com.day01.test8;

public class Test1 {
    public static void main(String[] args) {
        try{
            int num1 = 12;
            int num2 = 0;
            System.out.println("結果為:"+num1/num2);
        }catch(Exception ex){
            System.out.println("對不起,程式出現了錯誤" + ex);
        }finally {
            System.out.println("程式無論是否出現異常,這個邏輯都會執行的");
        }
        System.out.println("執行到這裡了!!!!!!!");
        System.out.println("執行到這裡了!!!!!!!");
        System.out.println("執行到這裡了!!!!!!!");
    }
}

finally:無論程式中是否出現異常程式都會執行finally中的程式碼塊

throw:自己進行異常的丟擲

throws:將該異常拋給呼叫該函式的函式

throw和throws的區別:

(1)位置不同:
throw:方法內部
throws:方法的簽名處,方法的宣告處
(2)內容不同:
throw+異常物件
throws+異常的型別
(3)作用不同:
throw:異常出現的源頭,製造異常,
throws:在方法的宣告處,告訴方法的呼叫者,這個方法中可能會出現我宣告的這些異
常。然後呼叫者對這個異常進行處理:要麼自己處理要麼再繼續向外丟擲異常。

集合

陣列的缺點-》 集合的優點

  • 陣列一旦指定了長度,那麼長度就被確定了,不可以更改。
  • 刪除,增加元素 效率低。
  • 陣列中實際元素的數量是沒有辦法獲取的,沒有提供對應的方法或者屬性來獲取
  • 陣列儲存:有序、可重複,對於無序的,不可重複的場合陣列不能滿足要求