1. 程式人生 > 實用技巧 >JavaSe第三天筆記小記

JavaSe第三天筆記小記

JavaSE第三天學習小記

1、java陣列

與c++中的陣列概念一致,把不同的只是語法

public class Hello {
    public static void main(String[] args) {
        /*效果相同
        int[] arr;  // 首選
        int arr[];  // 可用,但java中不建議用
         */
        int[] array1 = new int[5];      // 開闢五個存放int型別的陣列
        int[] array2 = {1, 2, 3};       // 開闢分別存放1,2,3的陣列 
        
        System.out.println("獲取陣列大小:" + array1.length);
    }
}

基本特點:

  • 長度確定,一旦被建立,大小不可改變
  • 存放元素必須是同一型別
  • 陣列中的元素可以是任何資料型別,包括基本型別和引用型別
  • 陣列變數屬於引用型別,陣列也可以看作是物件,陣列中的每個元素相當於該物件的成員變數
  • 陣列本身就是物件,java物件是在堆中的,因此陣列無論儲存原始型別還是其他物件型別,陣列本身都是在堆中的

三種初始化方式

1、靜態初始化

int[] arr = {1,2,3};
Man[] mans = {new Man(1), new Man(2)};

2、動態初始化

int[] arr = new int[2];
arr[0] = 1;
arr[1] = 2;

3、陣列的預設初始化

  • 陣列是引用型別,它的元素相當於類的例項變數,因此陣列一經分配空間,其中的每個元素也被按照例項變數同樣的方式被隱式初始化

2、記憶體分析


3、Arrays類

java中的一個工具類,包含在java.util.Arrays包中

  • 陣列本身沒有方法供我們呼叫,所以API中提供了一個工具類Arrays供我們使用,從而可以對資料物件進行一些基本的操作
  • 檢視JDK幫助文件
  • Arrays類中的方法都是static修飾的靜態方法,在使用的時候可以直接使用類名進行呼叫,而“不用”使用物件呼叫(是“不用”而不是“不能“)

常用方法:

  • 給陣列賦值:通過fill方法
  • 對陣列排序:通過sort方法,預設是從小到大排序
  • 比較陣列:通過equals方法比較陣列中元素值是否相等
  • 查詢陣列元素:通過binarySearch方法能對排序好的陣列進行二分查詢法操作

4、氣泡排序

動圖演示:

import java.util.Arrays;

public class Hello {
    public static void main(String[] args) {
        int[] arr = {21, 26, 12, 45, 23, 9, 12, 3, 3, 7};

        sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void sort(int[] a) {
        // 氣泡排序演算法實現
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = 0; j < a.length - 1 - i; j++) {
                if (a[j + 1] < a[j]) {
                    int tmp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = tmp;
                }
            }
        }
    }

}

結果:[3, 3, 7, 9, 12, 12, 21, 23, 26, 45]

5、面向物件

java中的面向物件思想與c++大體一致

  • 以類的方式組織程式碼,以物件的方式組織(封裝)資料

5.1 構造器

即構造方法(c++裡面的建構函式)

  • 必須和類的名字相同
  • 不能有返回型別,也不能寫void
  • 使用new關鍵字建立物件的本質是在呼叫構造器
  • 一旦定義了有參構造,就沒有預設的隱式無參建構函式,因此需要顯式定義

5.2 訪問許可權

修飾符 描述 大白話
private 私有的,被private修飾的類、方法、屬性、只能被本類的物件所訪問 我什麼都不跟別人分享。只有自己知道
default 預設的,在這種模式下,只能在同一個包內訪問 我的東西可以和跟我一塊住的那個人分享
protected 受保護的,被protected修飾的類、方法、屬性、只能被本類、本包、不同包的子類所訪問 我的東西我可以和跟我一塊住的那個人分享。另外也可以跟不在家的兒子分享訊息,打電話
public 公共的,被public修飾的類、方法、屬性、可以跨類和跨包訪問 我的東西大家任何人都可以分享

5.3 封裝

  • 程式設計追求“高內聚,低耦合”
  • 資料的隱藏,通常應禁止直接訪問一個物件中資料的實際表示,而應通過操作介面來訪問
  • 屬性私有,get/set

5.4 繼承

  • 繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模
  • extends的意思是擴充套件,子類是父類的擴充套件
  • java中只有單繼承,沒有多繼承
class People {
    String name;
    int age;
}

public class Student extends People{
    // 繼承了父類,具有父類的屬性
}

object類

  • java中所有的類,都預設直接或者間接繼承Object

super

  • super呼叫父類的構造方法,必須在構造方法的第一行
  • super必須只能出現在子類的方法或者構造方法中
  • super和this不能同時呼叫構造方法
  • 只能在繼承條件下才可以使用

this

  • 與super相比代表的物件不同:本身呼叫者這個物件
  • 沒有繼承也可以使用
this();		// 呼叫本類的構造
super();	// 呼叫父類的構造

5.5 重寫與多型

重寫:子類的方法與父類的方法必須相同,但是方法體不同

為什麼需要重寫:

  1. 父類的功能子類不一定需要或者不一定滿足

重寫的條件:

  • 方法名必須相同
  • 引數列表必須相同
  • 修飾符:範圍可以擴大但是不能縮小
  • 丟擲的異常:範圍可以被縮小但是不能擴大

多型:即同一方法可以根據傳送物件的不同而採取多種不同行為

  • 一個物件的實際型別是確定的,但是指向這個物件的引用的型別卻有很多
  • instanceof

存在的條件:

  1. 有繼承關係
  2. 子類重寫父類方法
  3. 父類引用指向子類物件

注意事項:

  • 多型是指方法的多型,屬性沒有多型
  • 父類和子類,有聯絡
  • 繼承關係,方法需要重寫,父類引用指向子類物件

靜態方法的呼叫(不叫重寫)

class A{
    public static void test(){
        System.out.println("A==>test()");
    }
}

public class B extends A{
    public static void test(){
        System.out.println("B==>test()");
    }
    
    public static void main(String[] args) {
        // 構造一個A類的物件
        A a1 = new A();
        a1.test();

        // 父類引用指向了子類
        A a2 = new B();
        a2.test();
    }
}

執行結果:

A==>test()
A==>test()

分析:靜態方法的呼叫只和左邊,即定義的資料型別有關

非靜態方法的重寫與呼叫

class A{
    public void test(){
        System.out.println("A==>test()");
    }
}

public class B extends A{
    // 子類重寫了父類的方法
    public void test(){
        System.out.println("B==>test()");
    }

    public static void main(String[] args) {
        // 構造一個A類的物件
        A a1 = new A();
        a1.test();

        // A型別的變數實際接受B型別的物件
        A a2 = new B();
        a2.test();
    }
}

執行結果:

A==>test()
B==>test()

分析:非靜態方法的呼叫和左邊和右邊都有關

  • 物件能否執行方法?得看指向這個物件的引用類中有沒有這個方法,即父類指向子類,不能呼叫子類獨有的方法
  • 物件執行什麼方法?得看右邊物件實際的型別來決定

5.6

class A{
}

public class B extends A{
    public static void main(String[] args) {
        B bb = new B();

        System.out.println(bb instanceof A);
    }
}

執行結果:

true


6、static

“static方法就是沒有this的方法。在static方法內部不能呼叫非靜態方法,反過來是可以的。而且可以在沒有建立任何物件的前提下,僅僅通過類本身來呼叫static方法。這實際上正是static方法的主要用途。”

用途:方便在沒有建立物件的情況下來進行呼叫(方法/變數)。

  1. static方法

static方法一般稱作靜態方法,因為不依賴任何物件,所以不存在this。

在靜態方法中不能訪問類的非靜態成員變數和非靜態成員方法,因為非靜態成員方法/變數都是必須依賴具體的物件才能夠被呼叫。

  1. static變數

​ static變數也稱作靜態變數,靜態變數和非靜態變數的區別是:靜態變數被所有的物件所共享,在記憶體中只有一個副本,它當且僅當在類初次載入時會被初始化。而非靜態變數是物件所擁有的,在建立物件的時候被初始化,存在多個副本,各個物件擁有的副本互不影響。

  static成員變數的初始化順序按照定義的順序進行初始化。

  1. static程式碼塊

static關鍵字還有一個比較關鍵的作用就是 用來形成靜態程式碼塊以優化程式效能。static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被載入的時候,會按照static塊的順序來執行每個static塊,並且只會執行一次

因此,很多時候會將一些只需要進行一次的初始化操作都放在static程式碼塊中進行。

注意

與C/C++中的static不同,Java中的static關鍵字不會影響到變數或者方法的作用域

在Java中能夠影響到訪問許可權的只有private、public、protected(包括包訪問許可權)這幾個關鍵字

在C/C++中static是可以作用域區域性變數的,但是在Java中切記:static是**不允許用來修飾區域性變數****


7、抽象類

// 抽象類, 抽象的抽象
public abstract class Action{
    // 制定約束,讓別人來實現
    // 只有方法定義,沒有方法的具體實現
    public abstract void doSomething();
}
  1. 抽象類不能建立物件,即不能new,只能靠子類去實現,而它本身只是制定了約束
  2. 抽象類中可以寫普通的方法
  3. 抽象方法必須在抽象類中,即如果一個類包含抽象方法,那麼該類必須是抽象類。
  4. 抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
  5. 任何子類必須重寫父類的抽象方法,或者宣告自身為抽象類。
  6. 構造方法,類方法(用 static 修飾的方法)不能宣告為抽象方法。

抽象類的建構函式

雖然抽象類不能被例項化,但可以有建構函式。由於抽象類的建構函式在例項化派生類之前發生,所以,可以在這個階段初始化抽象類欄位或執行其它與子類相關的程式碼。


8、介面

普通類:只有具體實現

抽象類:具體實現和規範(抽象方法)都有

介面:只有規範,專業的約束,約束和實現分離:面向介面程式設計

關鍵字:interface implements

  • 介面中的所有方法的定義都是抽象的,即public abstract,可省略,屬性都為public static final
  • java不支援多繼承,但是支援實現多介面,間接實現多繼承
  • 介面沒有構造方法
interface A {
    void say();
}

// 實現介面
public class Action implements A{

    @Override
    public void say() {
        System.out.println("Hello World!");
    }

    public static void main(String[] args) {
        new Action().say();
    }
}

執行結果:

Hello World!


9、內部類(奇葩!)

首先說明本質:無限套娃

9.1 成員內部類

public class Outer{
    int age = 11;

    public void out(){
        System.out.println("外部類的方法");
    }
	
    // 成員內部類
    public class Inner{
        public void in(){
            System.out.println("內部類的方法");
        }
    }


    public static void main(String[] args) {
        // 正常建立物件的形式
        Outer outer = new Outer();

        // 呼叫成員內部類的方法
        // 通過Outer的物件new一個Inner的物件,用Outer.Inner型別的引用接受
        Outer.Inner in = outer.new Inner();

        in.in();
    }
}

9.2 區域性內部類

public class Outer{

    public void method(){
        // 區域性內部類
        class Inner {
            public void in(){

            }
        }
    }

}

9.3 匿名內部類

interface User{
    void say();
}

public class Outer{
    public static void main(String[] args) {
        new User(){
            @Override
            public void say() {
                System.out.println("實現了介面的方法");
            }
        };
    }
}