主頁 > 後端開發 > Java學習-第一部分-第二階段-第一節:面向物件編程(高級)

Java學習-第一部分-第二階段-第一節:面向物件編程(高級)

2022-08-11 11:12:42 後端開發

面向物件編程(高級)

筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html)

類變數和類方法(static)

類變數

類變數-提出問題

提出問題的主要目的就是讓大家思考解決之道,從而引出我要講的知識點.說:有一群小孩在玩堆雪人,不時有新的小孩加入,請問如何知道現在共有多少人在玩?,撰寫程式解決,

傳統的方法來解決

使用我們現有的技術來解決這個問題,大家看看如何?

?思路

  1. 在main方法中定義一個變數count

  2. 當一個小孩加入游戲后count++,最后個count 就記錄有多少小孩玩游戲

    public class ChildGame {
        public static void main(String[] args) {
            //定義一個變數count,統計有多少小孩加入了游戲
            int count = 0;
            Child child1 = new Child("白精");
            child1.join();
            count++;
    
            Child child2 = new Child("老白");
            child2.join();
            count++;
            
            Child child3 = new Child("老白");
            child3.join();
            child3.count++;
            
            System.out.println("共有" + count + "小孩加入了游戲...");
        }
    }
    class Child {//類
        private String name;
        public Child(String name) {
            this.name = name;
        }
        public void join() {
            System.out.println(name + "加入了游戲..");
        }
    }
    

?問題分析:

  1. count是一個獨立于物件,很尷尬
  2. 以后我們訪問count很麻煩,沒有使用到OOP
  3. 3.因此,我們引出類變數/靜態變數

類變數快速入門

思考:如果,設計一個int count表示總人數,我們在創建一個小孩時,就把count加1,并且 count是所有物件共享的就ok了!,我們使用類變數來解決

public class ChildGame {
    public static void main(String[] args) {

        Child child1 = new Child("白精");
        child1.join();
        child1.count++;

        Child child2 = new Child("老白");
        child2.join();
        child2.count++;
        
        Child child3 = new Child("老白");
        child3.join();
        child3.count++;
        
        //......
        System.out.println("共有" + child1.count + "小孩加入了游戲...");
        System.out.println(child1.count);//3
        System.out.println(child2.count);//3
        System.out.println(child3.count);//3
        System.out.println(Child.count);//3
    }
}
class Child {//類
    private String name;
    //定義一個變數 count,是一個類變數(靜態變數)static靜態
    //該變數最大的特點就是會被Child類的所有的物件實體共享
    public static int count = 0;
    public Child(String name) {
        this.name = name;
    }
    public void join() {
        System.out.println(name + "加入了游戲..");
    }
}

其中child1,child2以及child3中的count指向相同空間,被共享,為同一值

jdk8以及之前,count(也就是靜態域)在方法區中,jdk8之后,jdk存放在堆中

有些書說在方法區... jdk版本有關系,記住一點: static變數是物件共享

不管static變數在哪里,共識:

  1. static變數是同一個類所有物件共享
  2. static類變數,在類加載的時候就生成了.

什么是類變數

類變數也叫靜態變數/靜態屬性,是該類的所有物件共享的變數,任何一個該類的物件去訪問它時,取到的都是相同的值,同樣任何一個該類的物件去修改它時,修改的也是同一個變數,這個從前面的圖也可看出來,

如何定義類變數

定義語法:

訪問修飾符 static 資料型別 變數名;[推薦]

static 訪問修飾符 資料型別 變數名;

class A{
    public static string name = "abc";
    static public int totalNum = 100;
}

如何訪問類變數

類名.類變數名

或者物件名.類變數名【靜態變數的訪問健飾符的訪問權限和范圍和普通屬性是一樣的,】

推薦使用:類名.類變數名;

public class Test {
    public static void main(String[] args) {
        //類名.類變數名
        // 說明:類變數是隨著類的加載而創建,所以即使沒有創建物件實體也可以訪問
        System.out.println(A.name);
        A a = new A();
        System.out.println("a.name=" +a.name);
    }
}

class A {
    //類變數
    public static String name = "韓順平";
}

類變數使用注意事項和細節討論

  1. 什么時候需要用類變數
    當我們需要讓某個類的所有物件都共享一個變數時,就可以考慮使用類變數(靜態變數):比如:定義學生類,統計所有學生共交多少錢,Student (name, fee)

  2. 類變數與實體變數(普通屬性)區別

    類變數是該類的所有物件共享的,而實體變數是每個物件獨享的,

  3. 加上static稱為類變數或靜態變數,否則稱為 實體變數/普通變數/非靜態變數

  4. 類變數可以通過類名.類變數名或者物件名.類變數名來訪問,但java設計者推薦我們使用 類名.類變數名 方式訪問,【前提是 滿足訪問修飾符的訪問權限和范圍】

  5. 實體變數不能通過類名.類變數名方式訪問,

  6. 類變數是在類加載時就初始化了,也就是說,即使你沒有助建家,只安尖加鄆,就可以使用類變數了,

  7. 類變數的生命周期是隨類的加載開始,隨著類消亡而銷毀,

類方法

類方法基本介紹

類方法也叫靜態方法,

形式如下:

訪問修飾符 static 資料回傳型別 方法名(){ }【推薦】
static 訪問修飾符 資料回傳型別 方法名(){ }

類方法的呼叫:

使用方式:類名.類方法名 或者 物件名.類方法名【前提是滿足訪問修飾符的訪問權限和范圍】

類方法應用案例

請大家看一個靜態方式小案例,(統計學費總和)

public class Test {
    public static void main(String[] args) {
        //創建2個學生物件,叫學費
        Stu tom = new Stu("tom");
        tom.payFee(100);
        Stu mary = new Stu("mary");
        mary.payFee(200);
        
        //輸出當前收到的總學費
        Stu.showFee();//300
    }
}

class Stu {
    private String name;//普通成員
    // 定義一個靜態變數,來累積學生的學費
    private static double fee = 0;

    public Stu(String name) {
        this.name = name;
    }

    //說明
    //1.當方法使用了static修飾后,該方法就是靜態方法
    //2.靜態方法就可以訪問靜態屬性/變數
    public static void payFee(double fee) {
        Stu.fee += fee;//累積到
        
    }
    public static void showFee() {
        System.out.println("總學費有:" + Stu.fee);
    }
}

類方法經典的使用場景

當方法中不涉及到任何和物件相關的成員,則可以將方法設計成靜態方法,提高開發效率,(不需要額外創建物件)

比如:工具類中的方法utils
Math類、Arrays類、Collections集合類看下原始碼:

小結
在程式員實際開發,往往會將一些通用的方法,設計成靜態方法,這樣我們不需要創建物件就可以使用了,比如列印一維陣列,冒泡排序,完成某個計算任務等..

舉例

public class Test {
    public static void main(String[] args) {
        System.out.println(MyTools.calSum(10,30));
    }
}

class MyTools {
    //開發自己的工具類時,可以將方法做成靜態的,方便呼叫class MyTools {
//求出兩個數的和
    public static double calSum(double n1, double n2) {
        return n1 + n2;
    }
}

類方法使用注意事項和細節討論

  1. 類方法和普通方法都是隨著類的加載而加載,將結構資訊存盤在方法區:類方法中無this的引數
    普通方法中隱含著this的引數
  2. 類方法可以通過類名呼叫,也可以通過物件名呼叫,
  3. 普通方法和物件有關,需要通過物件名呼叫,比如物件名.方法名(引數),不能通過類名調
    用,
  4. 類方法中不允許使用和物件有關的關鍵字,比如this和super,普通方法(成員方法)可以,[舉例]
  5. 類方法(靜態方法)中只能訪問靜態變數或靜態方法,【如何理解】
  6. 普通成員方法,既可以訪問普通變數(方法),也可以訪問靜態變數(方法),

小結:靜態方法,只能訪問靜態的成員,非靜態的方法,可以訪問靜態成員和非靜態成員(必須遵守訪問權限)

理解main方法語法

●深入理解main方法

解釋main方法的形式:public static void main(String[] args){}

  1. main方法時虛擬機呼叫

  2. java虛擬機需要呼叫類的main()方法,所以該方法的訪問權限必須是public

  3. java虛擬機在執行main()方法時不必創建物件,所以該方法必須是static

  4. 該方法接收String型別的陣列引數,該陣列中保存執行java命令時傳遞給所運行的類的引數,案例演示,接收引數.

  5. java 執行的程式 引數1 引數2 引數3

特別提示:

  1. 在main()方法中,我們可以直接呼叫main方法所在類的靜態方法或靜態屬性,

  2. 但是,不能直接訪問該類中的非靜態成員,必須創建該類的一個實體物件后,才能通過這個物件去訪問類中的非靜態成員

代碼塊

●基本介紹

代碼化塊又稱為初始化塊,屬于類中的成員[即 是類的一部分],類似于方法,將邏輯陳述句封裝在方法體中,通過{}包圍起來,
但和方法不同,沒有方法名,沒有回傳,沒有引數,只有方法體,而且不用通過物件或類顯式呼叫,而是加載類時,或創建物件時隱式呼叫,

●基本語法

[修飾符]{
? 代碼
};

注意:

  1. 修飾符可選,要寫的話,也只能寫static
  2. 代碼塊分為兩類,使用static修飾的叫靜態代碼塊,沒有static修飾的,叫普通代碼塊,
  3. 邏輯陳述句可以為任何邏輯陳述句(輸入、輸出、方法呼叫、回圈、判斷等)
  4. ;號可以寫上,也可以省略,

實體

package com.hspedu.p386;

public class codeBlock01 {
    public static void main(String[] args) {
        Movie movie = new Movie("你好,李煥英");
    }
}

class Movie {
    private String name;
    private double price;
    private String director;

    //3個構造器-》多載
    //老韓解讀
    //(1)下面的三個構造器都有相同的陳述句
    //(2)這樣代碼看起來比較冗余
    //(3)這時我們可以把相同的陳述句,放入到一個代碼塊中,即可
    //(4)這樣當我們不管呼叫哪個構造器,創建物件,都會先呼叫代碼塊的內容
    //(5)代碼塊呼叫的順序優先于構造器,,
    {
        System.out.println("電影螢屏打開...");
        System.out.println("廣告開始...");
        System.out.println("電影正是開始...");
    }

    public Movie(String name) {
        System.out.println("Hovie(Strihg name)被呼叫,.,");
        this.name = name;
    }

    public Movie(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public Movie(String name, double price, String director) {
        this.name = name;
        this.price = price;
        this.director = director;
    }
}

代碼塊使用注意事項和細節討論

  1. static代碼塊也叫靜態代碼塊,作用就是對類進行初始化,而且它隨著類的加載而執行,并且只會執行一次,如果是普通代碼塊,每創建一個物件,就執行,

  2. 類什么時候被加載

    ①創建物件實體時(new)
    ②創建子類物件實體,父類也會被加載
    ③使用類的靜態成員時(靜態屬性,靜態方法)

    案例演示: A類 extends B類 的靜態塊

  3. 普通的代碼塊,在創建物件實體時,會被隱式的呼叫,被創建一次,就會呼叫一次,
    如果只是使用類的靜態成員時,普通代碼塊并不會執行,

小結:

  1. static代碼塊是類加載時,執行,只會執行一次

  2. 普通代碼塊是在創建物件時呼叫的,創建一次,呼叫一次

  3. 類加載的3種情況,需要記住.

    public class Test {
        public static void main(String[] args) {
    //        new A();
    //        new A();
    //
    //        System.out.println("------------------");
    //        new B();
    
    //        System.out.println("------------------");
    //        System.out.println(A.a);
            System.out.println(B.b);
        }
    }
    
    class A {
        public static int a=10;
        static {//只在加載類時運行
            System.out.println("111111");
        }
        {//普通代碼塊,在new物件時,被呼叫,而且是每創建一個物件,就呼叫一次
         //可以這樣簡單的,理解普通代碼塊是構造器的補充
            System.out.println("普通");
        }
    }
    class B extends A{
        static {
            System.out.println("2222222");
        }
    }
    
  1. 創建一個物件時,在一個類呼叫順序是:(重點,難點)∶
    ①呼叫靜態代碼塊和靜態屬性初始化(注意:靜態代碼塊和靜態屬性初始化呼叫的優先級一樣,如果有多個靜態代碼塊和多個靜態變數初始化,則按他們定義的順序呼叫)
    ②呼叫普通代碼塊和普通屬性的初始化(注意:普通代碼塊和普通屬性初始化呼叫的優先級一樣,如果有多個普通代碼塊和多個普通屬性初始化,則按定義順序呼叫)
    ③呼叫構造方法,
  1. 構造器的最前面其實隱含了super()和呼叫普通代碼塊,新寫一個類,靜態相關的代碼塊,屬性初始化,在類加載時,就執行完畢,因此是優先于構造器和普通代碼塊執行的

    class A2 {
        public void A() { //構造器
            //這里有隱藏的執行要求
            //(1) super():這個知識點,在前面講解繼承的時候,老師說
            // (2)呼叫普通代碼塊的
            System.out.println("ok");
        }
    }
    
  2. 我們看一下創建一個子類時(繼承關系),他們的靜態代碼塊,靜態屬性初始化,普通代碼塊,普通屬性初始化,構造方法的呼叫順序如下:

    ①父類的靜態代碼塊和靜態屬性(優先級一樣,按定義順序執行)

    ②子類的靜態代碼塊和靜態屬性(優先級一樣,按定義順序執行)

    ③父類的普通代碼塊和普通屬性初始化(優先級一樣,按定義順序執行)

    ④父類的構造方法

    ⑤子類的普通代碼塊和普通屬性初始化(優先級一樣,按定義順序執行)

    ⑥子類的構造方法//面試題

public class Test {
    public static void main(String[] args) {
        //老師說明
        //(1)進行類的加載
        //1.1 先加載父類A02 1.2 再加載Bo2//(2)創建物件
        new B02();//物件
    }
}

class A02 {//父類
    private static int n1 = getVal01();
    static {
        System.out.println("A02的一個靜態代碼塊..");//2
    }
    {
        System.out.println("A02的第一個普通代碼塊..");//5
    }
    public int n3 = getVal02();
    public static int getVal01() {
        System.out.println("getVal01");//1
        return 10;
    }
    public int getVal02() {
        System.out.println("getVal02");//6
        return 10;
    }
    public A02() {
        System.out.println("A02的構造器");//7
    }
}

class B02 extends A02 { //
    private static int n3 = getVal03();
    static {
        System.out.println("BO2的一個靜態代碼塊..");//4
    }
    public int n5 = getVal04();
    {
        System.out.println("B02的第一個普通代碼塊..");//9
    }
    public static int getVal03() {
        System.out.println("getVal03");//3
        return 10;
    }
    public int getVal04() {
        System.out.println("getVal04");//8
        return 10;
    }
    public B02() {
        System.out.println("BO2的構造器");//10
    }
}
  1. 靜態代碼塊只能直接呼叫靜態成員(靜態屬性和靜態方法),普通代碼塊可以呼叫任意成員,

單例設計模式

什么是單例模式

  1. 所謂類的單例設計模式,就是采取一定的方法保證在整個的軟體系統中,對某個類只能存在一個物件實體,并且該類只提供一個取得其物件實體的方法
  2. 單例模式有兩種方式: 1)餓漢式 2)懶漢式

單例模式應用實體

演示餓漢式和懶漢式單例模式的實作,步驟如下:

  1. 構造器私有化=》防止直接new
  2. 類的內部創建物件
  3. 向外暴露一個靜態的公共方法,getInstance
  4. 代碼實作

餓漢式

public class Test {
    public static void main(String[] args) {
        GirlFriend instance = GirlFriend.getInstance();
        System.out.println(instance);

        GirlFriend instance2 = GirlFriend.getInstance();
        System.out.println(instance2);

        System.out.println(instance == instance2);//T
    }
}

class GirlFriend {
    private String name;
    //為了能夠在靜態方法中,回傳gf物件,需要將其修飾為static
    private static GirlFriend gf = new GirlFriend("小紅紅");
    //如何保障我們只能創建一個 GirlFriend物件
    //步驟
    //步驟[單例模式-餓漢式]
    //1,將構造器私有化
    // 2.在類的內部直接創建
    //3.提供一個公共的static方法,回傳 gf物件
    private GirlFriend(String name) {
        this.name = name;
    }

    public static GirlFriend getInstance() {
        return gf;
    }
}

懶漢式

package com.hspedu.test;

public class Test {
    public static void main(String[] args) {
        //new Cat("大黃");
        Cat instance = Cat.getInstance();
        System.out.println(instance);

    }
}

class Cat {
    private String name;
    private static Cat cat;//步驟

    //1.仍然構造器私有化
    //2.定義一個static屬性物件
    //3.提供一個public的static方法,可以回傳一個Cat物件
    private Cat(String name) {
        this.name = name;
    }

    public static Cat getInstance() {
        if (cat == null) {//如果沒有創建cat封象
            cat = new Cat("小可愛");
        }
        return cat;
    }
}

餓漢式VS懶漢式

  1. 二者最主要的區別在于創建物件的時機不同:餓漢式是在類加載就創建了物件實體,而懶漢式是在使用時才創建,

  2. 餓漢式不存在執行緒安全問題,懶漢式存在執行緒安全問題,(后面學習執行緒后,會完善)

  3. 餓漢式存在浪費資源的可能,因為如果程式員一個物件實體都沒有使用,那么餓漢式創建的物件就浪費了,懶漢式是使用時才創建,就不存在這個問題,

    在我們javaSE標準類中,java.lang.Runtime就是經典的單例模式,

final關鍵字

●基本介紹

final中文意思:最后的,最終的.
final 可以修飾類、屬性、方法和區域變數.
在某些情況下,程式員可能有以下需求,就會使用到final:

  1. 當不希望類被繼承時,可以用final修飾.

    final class A{ }
    class B extends A {}//會報錯
    
  2. 當不希望父類的某個方法被子類覆寫/重寫(override)時,可以用final關鍵字修飾,【案例演示:訪問修飾符 final 回傳型別方法名】

    class c {
    	//如果我們要求hi不能被子類重寫
    	//可以使用final修飾hi方法
    	public final void hi() {}
    }
    class D extends C {
        @0verride
    	public void hi {//報錯
    		System.out.println("重寫了C類的hi方法..");
    	}
    }
    
  3. 當不希望類的的某個屬性的值被修改,可以用final修飾.【案例演示: public final double TAX_RATE=0.08】

  4. 當不希望某個區域變數被修改,可以使用final修飾【案例演示: final double TAX_RATE=0.08)

    class F {
    	public void cry() {
    		//這時,NUM也稱為區域常量
        	final double NUM = 0.01;
            NUM= 0.9;//報錯
    		System.out.println("NUM=" + NUM);
    	}
    }
    

final使用注意事項和細節討論

  1. final修飾的屬性又叫常量,一般用XX_XX_XX 來命名

  2. final修飾的屬性在定義時,必須賦初值,并且以后不能再修改,賦值可以在如下位置之一【選擇一個位置賦初值即可】:

    ①定義時:如public final double TAX_RATE=0.08;
    ②在構造器中
    ③在代碼塊中,

  3. 如果final修飾的屬性是靜態的,則初始化的位置只能是
    ①定義時
    ②在靜態代碼塊賦值,不能在構造器中賦值,

  4. final類不能繼承,但是可以實體化物件,

  5. 如果類不是final類,但是含有final方法,則該方法雖然不能重寫,但是可以被繼承,

  6. 一般來說,如果一個類已經是final類了,就沒有必要再將方法修飾成final方法,(多此一舉)

  7. final不能修飾構造方法(即構造器)

  8. final和static往往搭配使用,效率更高,底層編譯器做了優化處理,

  9. 包裝類(Integer,Double,Float,Boolean等都是final),String也是final類,

抽象類

當父類的某些方法,需要宣告,但是又不確定如何實作時,可以將其宣告為抽象方法,那么這個類就是抽象類

abstract class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }
    //思考:這里eat這里你實作了,其實沒有什么意義//即:父類方法不確定性的問題
    //===>考慮將該方法設計為抽象(abstract)方法//===>所謂抽象方法就是沒有實作的方法
    //===>所謂沒有實作就是指,沒有方法體
    //===>當一個類中存在抽象方法時,需要將該類宣告為abstract類
    
//    public void eat() {
//        System.out.println("這是一個動物,但是不知道吃什么..");
//    }
    public abstract void eat() ;
}

抽象類的介紹

  1. 用abstract關鍵字來修飾一個類時,這個類就叫抽象類

    訪問修飾符 abstract 類名{
    }

  2. 用abstract關鍵字來修飾一個方法時,這個方法就是抽象方法
    訪問修飾符 abstract 回傳型別 方法名(引數串列);//沒有方法體

  3. 抽象類的價值更多作用是在于設計,是設計者設計好后,讓子類繼承并實作抽象類()

  4. 抽象類,是考官比較愛問的知識點,在框架和設計模式使用較多

抽象類使用的注意事項和細節討論

  1. 抽象類不能被實體化

    public class AbstractDetail01 {
        public static void main(String[] args) {
    		//抽象類,不能被實體化
            new A();//報錯
        }
    }
    abstract class A { 
    }
    
  2. 抽象類不一定要包含abstract方法,也就是說,抽象類可以沒有abstract方法

  3. 一旦類包含了abstract方法,則這個類必須宣告為abstract

    class B {//報錯
    	public abstract void hi();
    }
    
  4. abstract只能修飾類和方法,不能修飾屬性和其它的,

  5. 抽象類可以有任意成員【抽象類還是類】,比如:非抽象方法、構造器、靜態屬性等等

  6. 抽象方法不能有主體,即不能實作.如圖所示
    abstract void aaa(){......}//報錯,不能存在“{}”

  7. 如果一個類繼承了抽象類,則它必須實作抽象類的所有抽象方法,除非它自己也宣告為abstract類,[舉例 A類,B類,C類]

    //如果一個類繼承了抽象類,則它必須實作抽象類的所有抽象方法,除非它自己也宣告為abstract類
    abstract class E {
        public abstract void hi();
    }
    
    abstract class F extends E {
    }
    
    class G extends E {
        @Override
        public void hi() { //這里相等于G子類實作了父類E的抽象方法,所謂實作方法,就是有方法體
        }
    }
    
  8. 抽象方法不能使用private、final和static來修飾,因為這些關鍵字都是和重寫相違背的,

抽象類最佳實踐-模板設計模式

最佳實踐

需求

  1. 有多個類,完成不同的任務job
  2. 要求統計得到各自完成任務的時間
  3. 請編程實作

感情的自然流露

  1. 先用最容易想到的方法
  2. 分析問題,提出使用模板設計模式
public class Test {
	public static void main(String[] args) {
		new A().job();
		new B().job();
	}
}
//如果一個類繼承了抽象類,則它必須實作抽象類的所有抽象方法,除非它自己也宣告為abstract類
class A {
	public void job() {
        //得到開始的時間
        long start = System.currentTimeMillis();
        long num = 0;
        for (long i = 1; i <= 80000000; i++) {
        	num += i;
        }
        //得的結束的時間
        long end = System.currentTimeMillis();
        System.out.println("執行時間" + (end - start));
    }
}
class B {
    public void job() {
        //得到開始的時間
        long start = System.currentTimeMillis();
        long num = 0;
        for (long i = -10; i <= 800000; i++) {
            num += i;
        }
        //得的結束的時間
        long end = System.currentTimeMillis();
        System.out.println("執行時間" + (end - start));
    }
}

最佳實踐(使用動態系結機制)

設計一個抽象類(Template),能完成如下功能:

  1. 撰寫方法calculateTime( ,可以計算某段代碼的耗時時間
  2. 撰寫抽象方法job()
  3. 撰寫子類AA、BB,繼承抽象類Template,并實作job方法,
  4. 撰寫一個測驗類Test,看看是否好用,
public class Test {
    public static void main(String[] args) {
        AA aa = new AA();
        aa.calculateTime();
        BB bb = new BB();
        bb.calculateTime();
    }
}
abstract class Template {//抽象類-模板設計模式
    public abstract void job();//抽象方法
    public void calculateTime() {//實作方法,呼叫job方法
        //得到開始的時間
        long start = System.currentTimeMillis();
        job();
        //得的結束的時間
        long end = System.currentTimeMillis();
        System.out.println("執行時間" + (end - start));
    }
}
//如果一個類繼承了抽象類,則它必須實作抽象類的所有抽象方法,除非它自己也宣告為abstract類
class AA extends Template{
    public void job() {
        long num = 0;
        for (long i = 1; i <= 80000000; i++) {
            num += i;
        }
    }
}
class BB extends Template{
    public void job() {
        //得到開始的時間
        long num = 0;
        for (long i = -10; i <= 800000; i++) {
            num += i;
        }
    }
}

介面

為什么有介面

先看一張圖:

image

usb插槽就是現實中的介面,

你可以把手機,相機,u盤都插在usb插槽上,而不用擔心那個插槽是專門插哪個的,原因是做usb插槽的廠家和做各種設備的廠家都遵守了統一的規定包括尺寸,排線等等,

介面快速入門

這樣的設計需求在java編程/php/.net/go中也是會大量存在的,我曾經說過,一個程式就是一個世界,在現實世界存在的情況,在程式中也會出現,我們用程式來模擬一下,

介面

public interface UsbInterface {
    //規定介面的相關方法
    public void start();
    public void stop();
}

相機

public class Camera implements UsbInterface{//實作介面,就是把介面方法實作
    //IDEA中alt+insert,選擇implement methods(或ctrl+i)快速創建相應的方法
    @Override
    public void start() {
        System.out.println("相機開始作業");
    }
    @Override
    public void stop() {
        System.out.println("相機停止作業");
    }
}

手機

//Phone 類 實作 UsbInterface
//解讀1.即 Phone類需要實作UsbInterface介面 規定/宣告的方法
public class Phone implements UsbInterface{
    @Override
    public void start() {
        System.out.println("手機開始作業,..");
    }
    @Override
    public void stop() {
        System.out.println("手機停止作業..... ");
    }
}

電腦

public class Computer {
    //撰寫一個方法,計算機作業
    public void work(UsbInterface usbInterface) {
        usbInterface.start();
        usbInterface.stop();
    }
}

呼叫

public class Test {
    public static void main(String[] args) {
        //創建手機,相機物件
        Camera camera = new Camera();
        Phone phone = new Phone();
        //創建計算機
        Computer computer = new Computer();
        computer.work(phone);//把手機接入到計算機
        System.out.println("-----------------");
        computer.work(camera);
    }
}

●基本介紹

介面就是給出一些沒有實作的方法,封裝到一起,到某個類要使用的時候,在根據具體情況把這些方法寫出來,語法:

interface 介面名{
//屬性
//方法(1.抽象方法 2.默認實作方法 3.靜態方法)
}
class 類名 implements 介面{
自己屬性;
自己方法;
必須實作的介面的抽象方法
}

小結:

  1. 在Jdk7.0前介面里的所有方法都沒有方法體,即都是抽象方法,(已被淘汰,基本不用)
  2. Jdk8.0后介面可以有靜態方法,默認方法,也就是說介面中可以有方法的具體實作
interface AInterface {
    //寫屬性
    public int n1 = 10;//寫方法

    //在介面中,抽象方法,可以省略abstract關鍵字
    public void hi();

    //在jdk8后,可以有默認實作方法,需要使用default關鍵字修飾
    default public void ok() {
        System.out.println("ok ...");
    }

    //在jdk8后,可以有靜態方法
    public static void cry() {
        System.out.println("cry........");
    }
}

深入討

對初學者講,理解介面的概念不算太難,難的是不知道什么時候使用介面,下面我例舉幾個應用場景:

  1. 說現在要制造戰斗機,武裝直升機.專家只需把飛機需要的功能/規格定下來即可,然后讓別的人具體實作就可,
  2. 說現在有一個專案經理,管理三個程式員,功能開發一個軟體,為了控制和管理軟體,專案經理可以定義一些介面,然后由程式員具體實作,

注意事項和細節

  1. 介面不能被實體化

  2. 介面中所有的方法是public方法,介面中抽象方法,可以不用寫public和abstract,如下:

    void aa();實際上是public abstract void aa();

  3. 一個普通類實作介面,就必須將該介面的所有方法都實作,

    class Phone implements UsbInterface {//報錯
    }
    
  4. 抽象類實作介面,可以不用實作介面的方法,

    abstract class Phone implements UsbInterface {//不報錯
    }
    
  5. 一個類同時可以實作多個介面

    class Pig implements IB,IC {
    }
    
  6. 介面中的屬性,只能是final的,而且是public static final修飾符,比如:
    int a=1;實際上是public static final int a=1;(必須初始化)

  7. 介面中屬性的訪問形式:介面名.屬性名

  8. 一個介面不能繼承其它的類,但是可以繼承多個別的介面
    interface A extends B,C{}

  9. 介面的修飾符只能是public和默認,這點和類的修飾符是一樣的,

實作介面Vs繼承類

?介面和繼承解決的問題不同

繼承的價值主要在于:解決代碼的復用性和可維護性,
介面的價值主要在于:設計,設計好各種規范(方法),讓其它類去實作這些方法,即更加的靈活..

?介面比繼承更加靈活

介面比繼承更加靈活,繼承是滿足is -a的關系(小明是學生),而介面只需滿足like - a的關系(飛機像鳥一樣飛)

?介面在一定程度上實作代碼解耦[即:介面規范性+動態系結]

介面的多型特性(和類的繼承中的多型類似)

  1. 多型引數(前面案例體現)

    在前面的Usb介面案例,Usb usb,既可以接收手機物件,又可以接收相機物件,就體現了介面多型(介面參考可以指向實作了介面的類的物件)

  2. 多型陣列

    演示一個案例:給Usb陣列中,存放 Phone 和相機物件,Phone類還有一個特有的方法call),請遍歷Usb陣列,如果是Phone物件,除了呼叫Usb介面定義的方法外,還需要呼叫Phone特有方法call.

    Usb usbs[] = new Usb[2];
    usbs[0]= new Phone();
    usbs[1] = new Camera();
    for (int i = 0; i< usbs.length; i++){
        usbs[i].start();
        usbs[i].stop();
        if (usbs[i] instanceof Phone){
            ((Phone)usbs[i]).call();
        }
    }
    
  3. 介面存在多型傳遞現象,

    class InterfacePolyPass {
        public static void main(String[] args) {
            //介面型別的變數可以指向,實作了該介面的類的物件實體
            IG ig = new Teacher();
            //如果IG 繼承了IH 介面,而Teacher類實作了 IG介面
            // 那么,實際上就相當于Teacher類也實作了IH介面,
            //這就是所謂的介面多型多型傳遞現象.
            IH ih = new Teacher();
        }
    }
    interface IH {
        void hi();
    }
    interface IG extends IH {
    }
    class Teacher implements IG {
        @Override
        public void hi() {
        }
    }
    

類定義的進一步完善

image

內部類

基本介紹

一個類的內部又完整的嵌套了另一個類結構,被嵌套的類稱為內部類(inner class),嵌套其他類的類稱為外部類(outer class),是我們類的第五大成員【思考:類的五大成員是哪些?屬性 方法 構造器 代碼塊 內部類】,內部類最大的特點就是可以直接訪問私有屬性,并且可以體現類與類之間的包含關系,(難點)

●基本語法

class Outer{//外部類
	class Inner{//內部類
	}
}
class Other{//外部其他類
}

內部類的分類

定義在外部類區域位置上(比如方法內):

  1. 區域內部類(有類名)
  2. 匿名內部類(沒有類名,重點!!!!!!)

定義在外部類的成員位置上:

  1. 成員內部類(沒用static修飾)
  2. 靜態內部類(使用static修飾)

區域內部類的使用

說明:區域內部類是定義在外部類的區域位置,比如方法中,并且有類名.

  1. 可以直接訪問外部類的所有成員,包含私有的

  2. 不能添加訪問修飾符,因為它的地位就是一個區域變數,區域變數是不能使用修飾符的,但是可以使用final修飾,因為區域變數也可以使用final

  3. 作用域:僅僅在定義它的方法或代碼塊中,

  4. 區域內部類---訪問---->外部類的成員[訪問方式:直接訪問]

  5. 外部類---訪問---->區域內部類的成員
    訪問方式:創建物件,再訪問(注意:必須在作用域內)

  6. 外部其他類---不能訪問----->區域內部類(因為區域內部類地位是一個區域變數)

  7. 如果外部類和區域內部類的成員重名時,默認遵循就近原則,如果想訪問外部類的成員,則可以使用(外部類名.this.成員)去訪問

    System.out.println("外部類的n2=”+外部類名.this.n2);

記住:(1)區域內部類定義在方法中/代碼塊 (2)作用域在方法體或者代碼塊中 (3)本質仍然是一個類

public class Test {
    public static void main(String[] args) {
        Outer02 outer02 = new Outer02();
        outer02.m1();
    }
}

class Outer02 {//外部類
    private int n1 = 100;

    private void m2() {
        System.out.println("Outer02 m2()");
    }//私有方法

    public void m1() {//方法
        //1.區域內部類是定義在外部類的區域位置,通常在方法
        // 3.不能添加訪問修飾符,但是可以使用final修飾
        // 4.作用域︰僅僅在定義它的方法或代碼塊中
        String name = "xXx";
        final class Inner02 {//區域內部類(本質仍然是一個類)
            private int n1=800;
            //2.可以直接訪問外部類的所有成員,包含私有的
            public void f1() {
                //5.區域內部類可以直接訪問外部類的成員,比如下面外部類n1 和 m2()
                //7.如果外部類和區域內部類的成員重名時,默認遵循就近原則,如果想訪問外部類的成員,
                //   使用 外部類名.this.成員)去訪問
                System.out.println("n1=" + n1 +"外部類的n1="+Outer02.this.n1);
                m2();
            }
        }
        //6.外部類在方法中,可以創建Inner02物件,然后呼叫方法即可
        Inner02 inner02 = new Inner02();
        inner02.f1();

//        class Inner022 extends Inner02{
//        }
    }

    { //代碼塊
        class Inner03 {
        }
    }
}

匿名內部類的使用(重要!!!)

//(1)本質是類 (2)內部類 (3)該類沒有名字 (4)同時還是一個物件

必須繼承—個抽象類或者實作一個介面

說明:匿名內部類是定義在外部類的區域位置,比如方法中,并且沒有類名

  1. 匿名內部類的基本語法

    new 類或介面(引數串列){
    	類體
    };
    
  2. 匿名內部類的語法比較奇特,請大家注意,因為匿名內部類既是一個類的定義同時它本身也是一個物件,因此從語法上看,它既有定義類的特征,也有創建物件的特征,對前面代碼分析可以看出這個特點,因此可以呼叫匿名內部類方法,

  3. 可以直接訪問外部類的所有成員,包含私有的

  4. 不能添加訪問修飾符,因為它的地位就是一個區域變數,

  5. 作用域:僅僅在定義它的方法或代碼塊中,

  6. 匿名內部類---訪問---->外部類成員[訪問方式:直接訪問]

  7. 外部其他類---不能訪問----->匿名內部類(因為匿名內部類地位是一個區域變數)

  8. 如果外部類和匿名內部類的成員重名時,匿名內部類訪問的話,默認遵循就近原則如果想訪問外部類的成員,則可以使用(外部類名.this.成員)去訪問

例子(基于介面)

public class Test {
    public static void main(String[] args) {
        new Outer04().method();
    }
}

class Outer04 {//外部類
    private int n1 = 10;//屬性

    public void method() {//方法
        //基于介面的匿名內部類//老韓解讀
        //1.需求:想使用IA介面,并創建物件
        //2.傳統方式,是寫一個類,實作該介面,并創建物件
        //3.老韓需求是 Tiger/Dog 類只是使用一次,后面再不使用
        //4.可以使用匿名內部類來簡化開發
        //5.tiger的編譯型別? IA
        //6.tiger的運行型別?就是匿名內部類(物件名.getClass()可獲取名字)  Outer04$1
        /*我們看底層
        class XXXX implements IA {
            @override
            public void cry(O {
                System.out'.println("老虎叫喚...");
            }
        }
        */
        //7.jdk底層在創建匿名內部類Outer04$1,立即馬上就創建了Outer04$1實體,并且把地址
        // 回傳給tiger
        //8.匿名內部類使用一次,就不能再使用(但此處的tiger物件可重復使用)
        IA tiger = new IA(){
            @Override
            public void cry(){
                System.out.println("老虎叫喚");
            }
        };
        System.out.println("tiger的運行型別=" + tiger.getClass());
        tiger.cry();
        tiger.cry();
    }
}
interface IA {//介面
    public void cry();
}

例子(基于方法)

public class Test {
    public static void main(String[] args) {
        new Outer04().method();
    }
}

class Outer04 {//外部類
    private int n1 = 10;//屬性

    public void method() {//方法
        //演示基于類的匿名內部類
        // 分析
        //1.father編譯型別 Father
        //2.father運行型別Outer04$2
        //3.底層會創建匿名內部類
        /*
            class Outer04$1 extends Father{
                override
                public void test() {
                    System.out.println("匿名內部類重寫了test方法");
                }
            }
        */
        //4.同時也直接回傳了匿名內部類Outer04$2的物件
        Father tiger = new Father("jack") {

            public void test() {
                System.out.println("匿名內部類重寫了test方法");
            }
        };
        System.out.println("tiger的運行型別=" + tiger.getClass());//Outer04$1
        tiger.test();
        //基于抽象類的匿名內部類
        Animal animal = new Animal() {
            @Override
            void eat() {
                System.out.println("小狗吃骨頭...");
            }
        };
        animal.eat();
    }
}

class Father {//類

    public Father(String name) {//構造器
    }

    public void test() {//方法
    }
}

abstract class Animal {//抽象類
    abstract void eat();
}

成員內部類的使用

說明:成員內部類是定義在外部類的成員位置,并且沒有static修飾,

  1. 可以直接訪問外部類的所有成員,.包含私有的

  2. 可以添加任意訪問修飾符(public、protected、默認、private),因為它的地位就是一個成員,

  3. 作用域

    和外部類的其他成員一樣,為整個類體比如前面案例,在外部類的成員方法中創建成員內部類物件,再呼叫方法.

  4. 成員內部類---訪問---->外部類(比如:屬性)[訪問方式:直接訪問](說明)

  5. 外部類---訪問------>內部類(說明)訪問方式:創建物件,再訪問

  6. 外部其他類---訪問---->成員內部類

  7. 如果外部類和內部類的成員重名時,內部類訪問的話,默認遵循就近原則,如果想訪問外部類的成員,則可以使用(外部類名.this.成員)去訪問

public class Test {
    public static void main(String[] args) {
        Outer08 outer08 = new Outer08();
        outer08.t1();
        
        //6.外部其他類,使用成員內部類的兩種方式
        // outer08.new Inner08();相當于把 new Inner08()當做是outer08成員
        //這就是一個語法,不要特別的糾結.
		Outer08.Innter08 innter08 = outer08.new Innter08();
        
        //第二方式在外部類中,撰寫一個方法,可以回傳 Inner08物件
		Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
        
        
        
    }
}

class Outer08 {//外部類
    private int n1 = 10;
    public String name = "張三";
    private void hi() {
    	System.out.println("hi()方法...");
    }

    //1.注意:成員內部類,是定義在外部內的成員位置上
    //2.可以添加任意訪問修飾符(public、protected 、默認、private),因為它的地位就是一個成員
    private class Inner08 {//成員內部類
        private double sal = 99.8;
        public void say() {
            //4.可以直接訪問外部類的所有成員,包含私有的
            System.out.println("n1 = " + n1 + " name = " + name);
            hi();//4
        }
    }
    
    //方法,回傳一個Inner08實體
    public Inner08 getInner08Instance(){
		return new Inner08();
	}

    //寫方法
    public void t1() {
        //4.使用成員內部類
        //創建成員內部類的物件,然后使用相關的方法
        Inner08 inner08 = new Inner08();
        inner08.say();
        System.out.println(innerO8.sal);
    }
}

靜態內部類的使用

說明:靜態內部類是定義在外部類的成員位置,并且有static修飾

  1. 可以直接訪問外部類的所有靜態成員,包含私有的,但不能直接訪問非靜態成員
  2. 可以添加任意訪問修飾符(public.protected、默認、private),因為它的地位就是一個成員,
  3. 作用域:同其他的成員,為整個類體
  4. 靜態內部類---訪問---->外部類(比如:靜態屬性)[訪問方式:直接訪問所有靜
    態成員]
  5. 外部類---訪問------>靜態內部類訪問方式:創建物件,再訪問
  6. 外部其他類---訪問--->靜態內部類
  7. 如果外部類和靜態內部類的成員重名時,靜態內部類訪問的時,默認遵循就近原則,如果想訪問外部類的成員,則可以使用(外部類名.成員)去訪問
public class Test {
    public static void main(String[] args) {
        Outer10 outer10 = new Outer10();
        outer10.m1();

        //外部其他類使用靜態內部類
        // 方式1
        // 因為靜態內部類,是可以通過類名直接訪問(前提是滿足訪問權限)
        Outer10.Inner10 inner10 = new Outer10.Inner10();
        inner10.say();
        //方式2
        //撰寫一個方法,可以回傳靜態內部類的物件實體,
        Outer10.Inner10 inner101 = outer10.getInner10();
        System.out.println("============");
        inner101.say();

        Outer10.Inner10 inner10_ = outer10.getInner10_();
        System.out.println("============");
        inner10_.say();
    }
}

class Outer10 {//外部類
    private int n1 = 10;
    private static String name = "張三";
    private static void cry(){}
    // Inner10就是靜態內部類
    //1.放在外部類的成員位置
    //2.使用static修飾
    //3,可以直接訪問外部類的所有靜態成員,包含私有的,但不能直接訪問非靜態成員
    //4,可以添加任意訪問修飾符(public、 protected 、默認、private),因為它的地位就是一個成員//5,作用域:同其他的成員,為整個類體
    //5.作用域:同其他的成員,為整個類體
    static class Inner10 {
        private static String name ="李四";
        public void say() {
            System.out.println(name);
            System.out.println(Outer10.name);//7
            cry();
        }
    }
    public void m1() {
        Inner10 inner10 = new Inner10();
        inner10.say();
    }
    public Inner10 getInner10(){
        return new Inner10();
    }
    public static Inner10 getInner10_(){
        return new Inner10();
    }
}

這里:小結
(1)內部類有四種區域內部類,匿名內部類成員內部類,靜態內部類
(2)重點還是掌握匿名內部類使用

new 類/介面(引數串列){
	//...
};

(3)成員內部類,靜態內部類是放在外部類的成員位置,本質就是一個成員.
(4)其他細節看之前筆記...

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/501485.html

標籤:其他

上一篇:Java常用類(一)

下一篇:shiro認證- SpringBoot(20)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more