主頁 > 後端開發 > 八、Java面向物件編程

八、Java面向物件編程

2022-03-23 07:32:55 後端開發

Java面向物件

初識面向物件

面向程序 & 面向物件

面向程序思想

  • 步驟清晰簡單,第一步做什么,第二部做什么...
  • 面對程序適合處理一些較為簡單的問題

面向物件思想

  • 物以類聚,分類的思維模式,思考問題首先會解決問題需要哪些分類,然后對這些分類進行單獨思考,最后,才對某個分類下的細節進行面向程序思索,
  • 面向物件合適處理復雜的問題,適合處理需要多人協作的問題!

對于描述復雜的事物,為了從宏觀上把握、從整體上合理分析,我們需要使用面向物件的思路來分析整個系統,但是,具體到微觀操作,仍然需要面向程序的思路去處理,

什么是面向物件

面向物件編程(Object-Oriented Programming,OOP)

面向物件編程的本質是:以類的方式組織代碼,以物件的組織(封裝)資料

抽象:白話理解就是抽像,把像的的抽取出來,具體的理解還是抽像

三大特征:

  • 封裝
  • 繼承
  • 多型

從認識論角度考慮是先有物件后有類,物件,是具體是事物,類,是抽象的,是對物件的抽象

從代碼運行角度考慮是先有類后有物件,類是物件的模板

這些看不懂沒關系,后面慢慢的就會恍然大悟!


回顧方法及加深

? 一個真正的程式里面只有一個main方法,并不會像我們測驗的時候每個類里面都有,我們只是為了方便代碼的運行

回顧方法的定義

  • 修飾符

    • public:公共的,所有人都可以呼叫這個方法
    • static:靜態,方便呼叫 (可選)
  • 回傳型別

    • void:空的:不需要使用return回傳一個值(但是可以使用return結束方法)
    • 其他型別:需要使用return回傳一個值,回傳的值的型別要與其相對應
  • break和return的區別

    • break:跳出switch陳述句,和結束整個回圈;還有一個continue是結束一次回圈
    • return:結束當前方法,回傳一個結果(可以為空)
  • 方法名

    • 注意規范即可:見名知意,首字母小寫+駝峰原理
  • 引數串列

    • (引數型別 引數名,...) 可以多個,還有一個 可變引數(引數型別... 引數名)
package com.xiaodi.operator.oop.demo01;

//Demo01 類
public class Demo01 {

    //main 方法
    public static void main(String[] args) {

    }

    /*
    方法的定義:
        修飾符 回傳值型別 方法名(...) {
            //方法體
            return 回傳值;
        }
    */
    public String sayHello() {
        return "Hello,World";
    }

    public double max(double a, double b) {
        return a > b ? a : b; //三元運算子
    }
}
  • 例外拋出
    • 疑問 (后面講解)

回顧方法的呼叫

  • 靜態方法

    • 靜態方法:加static的為靜態方法
    package com.xiaodi.operator.oop.demo01;
    
    //學生類
    public class Sudent {
        //靜態方法 static
        public static void say() {
            System.out.println("學生說話");
        }
    }
    
    • 靜態方法的呼叫
    package com.xiaodi.operator.oop.demo01;
    
    public class Demo02 {
        public static void main(String[] args) {
            //靜態方法呼叫:類名.方法名;
            Sudent.say();
        }
    
    }
    
  • 非靜態方法

    • 非靜態方法:沒加static的為非靜態方法
    package com.xiaodi.operator.oop.demo01;
    
    //學生類
    public class Sudent {
        //非靜態方法
        public void say() {
            System.out.println("學生說話");
        }
    }
    
    • 非靜態方法的呼叫
    package com.xiaodi.operator.oop.demo01;
    
    public class Demo02 {
        public static void main(String[] args) {
            //非靜態方法呼叫
            //先實體化這個類 new ;物件型別 物件名 = new 物件值;
            Sudent sudent = new Sudent();
            //然后呼叫
            sudent.say();
        }
    }
    
    • 特殊情況 原因:static 是和類一起加載的,這個類存在的時候它就存在,時間片非常早;普通方法是類實體化后才存在的

      • 兩個普通方法(非靜態) 或 兩個靜態方法:可以直接相互呼叫,無需實體化
      package com.xiaodi.operator.oop.demo01;
      
      public class Demo02 {
          public static void main(String[] args) {}
      
          //兩個普通方法(非靜態):可以直接相互呼叫,無需實體化
          public void a() {
              b();
          }
      
          public void b() {}
      
          public static void c() {
              d();
          }
      
          public static void d() {}
      }
      
      • 兩個方法中一個一個為普通方法,一個為靜態方法,如果靜態方法呼叫非靜態,就要實體化;非靜態呼叫靜態無須實體化
      package com.xiaodi.operator.oop.demo01;
      
      public class Demo02 {
          public static void main(String[] args) {}
      
          public static void a() {
              Demo02 demo02 = new Demo02();
              demo02.b();
          }
      
          public void b() {}
      }
      
  • 形參和實參:形式引數和實際引數的型別要對應

    • 形式引數:是定義方法時的引數;例如:如下代碼的(int a, int b)就是形式引數
    package com.xiaodi.operator.oop.demo01;
    
    public class Demo03 {
        public static void main(String[] args) {
    
        }
    
        public int add(int a, int b) {
            return a+b;
        }
    }
    
    • 實際引數:是呼叫方法傳遞給方法的引數;例如:如下代碼的demo03.add(1, 2);
    package com.xiaodi.operator.oop.demo01;
    
    public class Demo03 {
        public static void main(String[] args) {
            Demo03 demo03 = new Demo03();
            demo03.add(1,2);
        }
    
        public int add(int a, int b) {
            return a+b;
        }
    }
    
  • 值傳遞和參考傳遞

    • 值傳遞參考傳遞的概念

      • 值傳遞是指在呼叫方法時將實際引數復制一份傳遞到方法中,這樣在方法中如果對引數進行修改,將不會影響到實際引數,
      package com.xiaodi.operator.oop.demo01;
      
      //值傳遞
      public class Demo04 {
          public static void main(String[] args) {
              int a = 1;
              System.out.println(a); //1
      
              Demo04.change(a);
      
              System.out.println(a); //1
          }
      
          //回傳值為空
          public  static  void  change(int a) {
              a = 10;
          }
      }
      
      • 所謂參考傳遞是指在呼叫方法時將實際引數的地址傳遞到方法中,那么在方法中對引數所進行的修改,將影響到實際引數,
      package com.xiaodi.operator.oop.demo01;
      
      //參考傳遞:java本質還是值傳遞
      public class Demo05 {
          public static void main(String[] args) {
              Perosn perosn = new Perosn();
      
              System.out.println(perosn.name);//nell
      
              Demo05.change(perosn);
      
              System.out.println(perosn.name);//曉迪
          }
      
          public static void change(Perosn perosn) {
              perosn.name = "曉迪";
          }
      }
      
      //定義了一個Perosn類,有一個屬性:name
      class Perosn {
          String name;//null
      }
      
    • 值傳遞和參考傳遞的理解

      • 值傳遞 在方法的呼叫程序中,實參把它的實際值傳遞給形參,此傳遞程序就是將實參的值復制一份傳遞到方法中,這樣如果在方法中對該值(形參的值)進行了操作將不會影響實參的值,因為是直接復制,所以這種方式在傳遞大量資料時,運行效率會特別低下,
      • 參考傳遞 參考傳遞彌補了值傳遞的不足,如果傳遞的資料量很大,直接復過去的話,會占用大量的記憶體空間,而參考傳遞就是將物件的地址值傳遞過去,方法接收的是原始值的首地址值,在方法的執行程序中,形參和實參的內容相同,指向同一塊記憶體地址,也就是說操作的其實都是源資料,所以方法的執行將會影響到實際物件,
    • java本質還是值傳遞(為什么這么說:參考傳遞是里面存的首地址的copy,原來參考變數里的的物件你不能改,但是他指向的堆物件你可以改啊,)

    • 結論:

      • 值傳遞,相當于拷貝一份值,對引數的修改不影響原有引數
      • 參考型別傳參考,形參和實參指向同一個記憶體地址(同一個物件),所以對引數的修改會影響到實際的物件,

上面還寫了一個class(劇透了內部類的內容(后面會講)) 一個類里面只能有一個public class 但是能有多個class

  • this關鍵字 (講到繼承的時候再講)

值傳遞和參考傳遞大家肯定覺得很繞,這是因為我們對 物件和從記憶體分析的理解還不透徹,本章后面后面的內容學完再來看一遍,肯定會恍然大悟!


物件的創建*

類與物件的關系

類是一種抽象的資料型別,它是對某一類事物整體描述/定義,但并不能代表某一個具體的事物

  • 如動物、植物、手機、電腦

  • Person類、Pet類、Car類等,這些類都是用來描述/定義某一類具體的事物應該具備的特點和行為

物件是抽象概念的具體實體

  • 張三就是的一個具體實體,張三家里的旺財就是的一個具體實體
  • 能夠體現出特點,展現出功能的是具體的實體,而不是一個抽象的概念

創建與初始化物件

以后我們就不要在每一個類里面都去加上main方法,一個程式只有一個主啟動類

一個專案只存在一個main方法

我們新建一個包,先來一個Student類,再來一個Application類,Application類定義一個main方法就好也是唯一的一個入口,

我們再IDEA上面,把Application類列到一邊,方便我們隨時進行測驗,如圖下

方便測驗的方法

使用new關鍵字創建物件

package com.xiaodi.operator.oop.demo01.demo02;

//學生類
public class Student {
    //不管再厲害的人寫的類里面只可能存在兩個東西,1就是屬性 2就是方法
    //屬性:可以理解為欄位
    String name;
    int age;

    //方法
    public void study() {
        //this.代表當前這個類的
        System.out.println(this.name+"在學習");
    }
}

這樣我們一個簡單的類就定義出來了

package com.xiaodi.operator.oop.demo01.demo02;

//一個專案應該只存在一個main方法
public class Application {
    public static void main(String[] args) {
        //類是抽象的,我們需要把這個類實體化
        //類實體化后會回傳一個自己的物件!
        //student物件就是一個Student類的具體實體!
        Student student = new Student();

        Student xiaoming = new Student();
        Student xiaohong = new Student();
        //類是抽象的可以這么理解:類就相當一個模板,沒有具體的值

        xiaoming.name = "小明";
        xiaoming.age = 17;
        System.out.println(xiaoming.name);
        System.out.println(xiaoming.age);

        System.out.println(xiaohong.name);//默認值null
        System.out.println(xiaohong.age);//默認值0
        //由此可見,同一個類new過來的物件是互不影響的,是一個具體的實體
    }
}

Student類就是一個抽象的模板,然后我們通過new關鍵字,可以創建不一樣的具體的實體!

大家現在再品一下這句話:以類的方式組織代碼,以物件的組織(封裝)資料,是不是恍然大悟!

構造器詳解

使用new關鍵字創建的時候,除了分配記憶體空間之外,還會給 創建好的物件 進行默認的初始化 以及對類中構造器的呼叫

package com.xiaodi.operator.oop.demo01.demo02;

public class Person {
    
}
package com.xiaodi.operator.oop.demo01.demo02;

//一個專案應該只存在一個main方法
public class Application {
    public static void main(String[] args) {
        Person person = new Person();
    }
}

Person這個類里面我們沒有寫方法,但是還是能new一個實體出來,就證明類里面有一些默認的東西

這個物件是怎么來的,為什么能憑空new出來,我們去看這個Person類生成的class檔案

我們在IDEA點開專案架構,選擇modules,再選擇新增一個目錄(Add Content Root),選擇我們的out目錄,找到對應的class檔案打開就行(如果沒有對應的class檔案,在IDEA運行一下檔案就會生成) Person.class檔案內容如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.xiaodi.operator.oop.demo01.demo02;

public class Person {
    public Person() {
    }
}

你會發現默認的幫我們加了一個方法而且這個方法沒有回傳值,方法名字和類名相同;其實這就是一個構造器,

得出結論:一個類即使什么都不寫,它也會存在一個方法

  • 類中的構造器也稱為構造方法,是在進行創建物件的時候必須呼叫的,并且構造器有以下兩個特點:
    • 1、必須和類的名字相同
    • 2、必須沒有回傳型別,也不能寫void

在.java檔案顯示的定義構造器:

package com.xiaodi.operator.oop.demo01.demo02;

public class Person {
    public Person() {
        
    }
}

那么有人就會問,這個無參構造器能干什么:

package com.xiaodi.operator.oop.demo01.demo02;

public class Person {

    //給我們初始化一些資訊
    String name;

    //作用
    //1、使用new關鍵字,本質是在呼叫構造器
    //2、用來初始化值
    public Person() {
        this.name = "XiaoDi";
    }

    //有參構造:一旦定義了有參構造,無參構造就必須顯示定義
    public Person(String name) {
        this.name = name;
    }


    //快捷鍵:Alt+Insert ,選擇Constructor能自動生成構造器,引數能選
}
package com.xiaodi.operator.oop.demo01.demo02;

//一個專案應該只存在一個main方法
public class Application {
    public static void main(String[] args) {
        //我們可以多載很多個構造器,使用new實體化一個物件的時候,他會根據你傳的引數來判斷你呼叫的是哪個構造器
        Person person = new Person();
        Person person1 = new Person("XiaoDi");

        System.out.println(person.name);//null
        System.out.println(person1.name);//XiaoDi
    }
}

構造器總結:

? 構造器定義需注意:

  • 和類名相同
  • 沒有回傳值

? 構造器的作用:

  • 使用new關鍵字的時候構造器就執行了
  • 初始化物件的值

? 注意點:

  • 定義了有參構造之后,如果想要使用無參構造,就必須顯示的去定義一個無參構造
  • 我們可以多載很多個構造器,使用new實體化一個物件的時候,他會根據你傳的引數來判斷你呼叫的是哪個構造器

? 快捷鍵:

  • 在IDEA中使用 Alt+Insert ,選擇Constructor能自動生成構造器,引數能選

構造器必須要掌握

類與物件簡單小結

1、類與物件

  • 類是一個模板(抽象),物件是一個具體的實體

2、方法

  • 定義、呼叫

3、物件的參考

  • 參考型別、基本型別(8)

  • 物件是通過參考來操作的

4、屬性:也叫欄位(Field)、或成員變數

? 默認初始化:

? 數字:0、0.0;

? char:u0000(轉化為int型別輸出0);

? boolean:false;

? 參考:null

? 屬性的定義:修飾符 屬性型別 屬性名 = 屬性值;

5、物件的創建和使用

  • 必須使用new關鍵字創造物件、構造器 :Person xiaodi = new Person();
  • 物件的屬性 xiaodi.name;
  • 物件的方法 xiaodi.sleep();

6、類

  • 類里面只能寫屬性方法

面向物件三大特性

封裝

  • 該露的露,該藏的藏:比如遙控器,暴露一些開關換臺鍵就行,一些底層的就藏起來,用戶不需要全部了解
    • 我們程式設計要追求“高內聚,低耦合”,高內聚:就是類的內部資料操作細節自己完成,不允許外部干涉;低耦合:僅暴露少量的方法給外部使用,
  • 封裝(資料的隱藏)
    • 通常,應禁止直接訪問一個物件中資料的實際表示,而應該通過操作介面來訪問,這稱為資訊隱藏
  • 記住這句話就夠了:屬性私有,get\set

聽不懂沒關系上代碼:

package com.xiaodi.operator.oop.demo03;

//學生類
public class Student {

    //私有屬性    private:私有
    private String name; //名字
    private int age; //年齡
    private int id; //學號
    private char sex; //性別

    //提供一些可以操作這個屬性的方法!
    //提供一些public 的 get、set方法

    //get 獲取這個資料
    public String getName() {
        return this.name;
    }

    //set 給這個資料設定值
    public void setName(String name) {
        this.name = name;
    }

    //記住Alt+Insert快捷鍵然后選擇Getter 或者Setter 或者Getter and Serter然后能選擇私有屬性進行快速生成

    //有人就會問了,封裝有啥子用(可以避免用戶去破壞這個系統,輸入一些注入漏洞代碼 或 輸入一些不符合實際的東西)
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 120 || age < 0) { //不合法
            this.age = 3;
        }else {
            this.age = age;
        }
    }

}
package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo03.Student;

public class Application {
    public static void main(String[] args) {
        Student s1 = new Student();

        //當屬性加上private之后就變成私有了
        //是不能像原來那樣呼叫的;原來那樣呼叫是因為屬性是public公共的,
        //s1.name = "xiaodi"; 這樣是會報紅的

        //通過類中公共方法呼叫、和修改
        //get 訪問
        String name = s1.getName();

        //set 修改
        s1.setName("曉迪");

        //輸出看一下
        System.out.println(s1.getName());

        //封裝的作用
        s1.setAge(999);
        System.out.println(s1.getAge());//不符合就表示用戶連基本的嘗試都沒有估計是個兒童,直接定義為3歲即可
    }

}

總結->封裝的意義:

  • 1、提高程式安全性,保護資料
  • 2、隱藏代碼實作細節
  • 3、統一介面
  • 4、提高了系統的可維護性

作用在什么地方:這就要通過大家平時多寫代碼去積累經驗了,大家現在還只是學會了這樣一個操作,不知道什么地方需要使用到,在我們后面的學習中就會經常去寫封裝這個東西,大家到時候慢慢積累就行,

聊一聊方法多載:比如我們的println,為什么它啥都能輸出,就是因為它多載了很多方法,方法的引數定義的不同,實作不同型別的輸出;大家可以在IDEA中按住Ctrl鍵然后點擊println進去看一下

繼承

  • 繼承的本質是對某一批類的抽象,從而實作對現實世界更好的建模,

  • extends的意思是“擴展”,子類是父類的擴展,

  • Java中類只有單繼承,沒有多繼承! (可以理解為一個兒子只能有一個爸爸,一個爸爸能有多個兒子)

  • 繼承是類和類之間的一種關系,除此之外,類和類之間的關系還有依賴、組合,聚合等

  • 繼承關系的兩個類,一個為子類(派生類),一個為父類(基類),子類繼承父類,使用關鍵字extends來表示

  • 子類和父類之間,從意義上講應該具有“is a”的關系,(比如:Wangcai is a dog )

上代碼理解:

Person 人 父類

package com.xiaodi.operator.oop.demo04;

//Person 人 : 父類
public class Person {

    //public 公共的,子類能繼承
    //protected 受保護的
    //default 不寫,默認
    //private 私有的,子類不能繼承;一般屬性才會是私有的
    public int money = 10_0000; //公共的
    private int money1 = 10_0000_0000; //私有的,子類就不能繼承,但是可以通過封裝思想,留一些可以使用這些錢的方法

    public void say() {
        System.out.println("說話");
    }

    public int getMoney1() {
        return money1;
    }

    public void setMoney1(int money1) {
        this.money1 = money1;
    }
}

Student 學生 子類

package com.xiaodi.operator.oop.demo04;

//學生也是人 所以繼承人 :派生類或子類
public class Student extends Person {
    //子類可以繼承父類的所有方法、以及屬性;
}

Application 啟動方法(測驗)

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo04.Student;

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student.money); //父類的屬性 (public)
        student.say(); //父類的方法(public)

        // System.out.println(student.money1);
        // (private)私有的不能繼承,但是可以通過 父類給我留的方法去使用
        System.out.println(student.getMoney1());
    }
}

繼承小總結:

  • 關鍵字:extends;語法:在類名后面加上:[extends 要繼承的類名]
  • 子類繼承父類所有方法以及公共屬性
  • 私有屬性是不能繼承的(但是一般情況下是會通過封裝的一些方方法去呼叫或修改);

Object類

記住一個快捷鍵Ctrl+H:查看當前繼承的繼承情況

當我們Person類什么都不寫的情況下,new一個Person物件,然后輸入person.就能點出一些方法,但是我們什么都沒定義這是為什么呢?

package com.xiaodi.operator.oop.demo04;

//Person 人
//在Java中,所有的類,都默認直接或者間接繼承Object
public class Person /*extends Object*/{


}
package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo04.Person;

public class Application {
    public static void main(String[] args) {
        Person person = new Person();
        //person.(equals(),hashCode(),toString()......)
    }

}
  • 在Java中,所有的類,都默認直接或者間接繼承Object類(如果是間接繼承,那么Object就是它的爺爺,因為Java中類只有單繼承,沒有多繼承)

super詳解

  • this是代表當前類的
  • super是代表父類的

? 父類:Person

package com.xiaodi.operator.oop.demo04;

//Person 人
public class Person /*extends Object*/{
    //修飾符 protected 受保護的
    protected String name = "曉迪";

    public void print() {
        System.out.println("Person");
    }
}

? 子類:Student

package com.xiaodi.operator.oop.demo04;

//學生也是人 所以繼承人 :派生類或子類
public class Student extends Person {
    private String name = "小迪";

    public void print() {
        System.out.println("Student");
    }

    public void text(String name) {
        System.out.println(name);//方法里的name
        System.out.println(this.name);//當前類的name
        System.out.println(super.name);//父類的name
    }

    public void text1() {
        print();//這個是當前類的print
        this.print();//這個也是當前類的print(建議寫法)
        super.print();//父類里的print
    }
}

? 啟動程式(測驗):Application

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo04.Student;

public class Application {
    public static void main(String[] args) {
        Student student = new Student();

        student.text("XiaoDi");
        System.out.println();//換行符
        student.text1();
    }
}

輸出結果:

? XiaoDi
? 小迪
? 曉迪

? Student
? Student
? Person

想一下如果new子類的時候構造器的執行順序是怎么樣的:

? 父類:Person

package com.xiaodi.operator.oop.demo04;

//Person 人
public class Person /*extends Object*/{
    public Person() {
        System.out.println("Person無參構造執行了");
    }
}

? 子類:Student

package com.xiaodi.operator.oop.demo04;

//學生也是人 所以繼承人 :派生類或子類
public class Student extends Person {
    public Student() {
        super();//子類構造器隱藏代碼,在構造器的第一行,這一行不寫效果也是一樣的
        //this("xiaodi"); 我們要呼叫自己的有參構造this("xiaodi");,也需要放在第一行,否則報錯,也就是說兩者在同一個構造器里只能使用一個;

        System.out.println("Student無參構造執行了");
    }
    public String name;

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

? 啟動程式(測驗):Application

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo04.Student;

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

輸出:

? Person無參構造執行了
? Student無參構造執行了

也就是說父類的無參構造器先執行了

  • 如果說我們要呼叫自己的有參構造this("xiaodi");,也需要放在第一行,否則報錯,也就是說兩者在同一個構造器里只能使用一個;這個就是super關鍵字坑爹的地方

那么假如我的父類里面沒有無參構造器:

? 父類:Person

package com.xiaodi.operator.oop.demo04;

//Person 人
public class Person /*extends Object*/{
    public String name;
    
    public Person(String name) {
        this.name = name;
    }
}

? 子類:Student

package com.xiaodi.operator.oop.demo04;

//學生也是人 所以繼承人 :派生類或子類
public class Student extends Person {
    public Student() {//報錯
        System.out.println("Student無參構造執行了");
    }

}
  • 會直接導致子類的無參構造也寫不了

但是也不是沒有辦法,沒有無參構造,那你顯示的寫出呼叫父類的有參構造就行了:

? 子類:Student

package com.xiaodi.operator.oop.demo04;

//學生也是人 所以繼承人 :派生類或子類
public class Student extends Person {
    public Student() {
        super("小迪");
        System.out.println("Student無參構造執行了");
    }

}

super小總結:

  • 1、super是在子類中呼叫父類的屬性或者方法 例如:super.name; super.print();(只能出現在子類的方法或構造方法中
  • 2、super呼叫父類的構造方法,必須在子類的構造方法的第一個(是隱藏代碼,寫不寫效果是一樣的)
  • super呼叫父類構造 和 this呼叫本類(子類)有參構造 不能同時在一個構造方法里面使用(也就是說能通過騷操作來解決):

? 父類:Person

package com.xiaodi.operator.oop.demo04;

//Person 人
public class Person /*extends Object*/{

    public Person() {
        System.out.println("Person無參構造執行了");
    }
    public String name;
}

? 子類:Student

package com.xiaodi.operator.oop.demo04;

//學生也是人 所以繼承人 :派生類或子類
public class Student extends Person {
    public Student() {//報錯
        this(18);

        System.out.println("Student無參構造執行了");
    }
    public int age;
    
    public Student(int age) {
        super();
        this.age = age;
    }
}

? 如果要呼叫子類中的有參構造方法的話,且不影響代碼,就能像上面這種方法寫:呼叫子類有參構造的同時還呼叫了父類的無參構造,以上代碼的執行順序是:1父類無參構造、2age=18、3子類無參構造

super VS this

  • 代表的物件不同
    • this:本身呼叫者這個物件
    • super:代表父類物件的應用
  • 前提:
    • this:沒有繼承也可以使用
    • super:只能在繼承的條件下才能使用
  • 構造方法:
    • this():本類的構造
    • super():父類的構造

方法重寫

靜態方法

? 父類:B

package com.xiaodi.operator.oop.demo04;

//重寫都是方法重寫,和屬性無關
public class B {
    public static void test() {
        System.out.println("B->test()");
    }
}

? 子類:A

package com.xiaodi.operator.oop.demo04;

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

? 啟動程式:Application

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo04.A;
import com.xiaodi.operator.oop.demo04.B;

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

        A.test();

        B.test();
    }
}

輸出:

? A->test()
? B->test()

非靜態方法

? 父類:B

package com.xiaodi.operator.oop.demo04;

//重寫都是方法重寫,和屬性無關
public class B {
    public void test() {
        System.out.println("B->test()");
    }
}

? 子類:A

package com.xiaodi.operator.oop.demo04;

public class A extends B{
    //這里使用Alt+Insert快捷鍵生成重寫選擇 有Override的

    //Override:重寫
    @Override //注解:有功能的注釋!這個不用糾結我們后面會單獨講
    public void test() {
        System.out.println("A->test()");
    }
}

啟動程式:Application

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo04.A;
import com.xiaodi.operator.oop.demo04.B;

public class Application {

    //靜態方法和非靜態方法區別很大!
        //靜態方法:方法的呼叫只和左邊定義的資料型別有關(這個不叫重寫)
        //非靜態方法:非靜態(且修飾符只能是public):子類重寫了父類的方法(這個才叫重寫)
    public static void main(String[] args) {
        //
        A a = new A();
        a.test(); //A

        //父類的參考指向了子類
        B b = new A();//子類重寫了父類的方法
        b.test();//B
    }
}

方法重寫小總結:

  • 首先需要有繼承關系,子類重寫父類的非靜態方法!

特點:

  • 1、方法名必須相同
  • 2、引數串列必須相同 (多載是當前類的,而且引數串列不相同)
  • 3、修飾符:重寫時子類的訪問控制修飾符不能比父類的范圍小(public>protected>default>private)(這個先不要糾結,隨著后面的學習再來看這個筆記)
  • 拋出的例外;范圍可以被縮小,但不能擴大;(后面再去了解)ClassNotFoundException -->Exception(大)

重寫,子類的方法和父類必須要一致;方法體不同!

為什么要重寫:

  • 1、父類的功能,子類不一定需要,或者不一定滿足!

快捷鍵:Alt+Insert,然后選擇override

多型

多型

  • 即同一方法可以根據發送物件的不同而采用多種不同的行為方式

  • 一個物件的實際型別是確定的,但可以指向物件的參考的型別有很多

  • 多型存在的條件

    • 有繼承關系
    • 子類重寫父類的方法
    • 父類參考指向子類物件
  • 注意:多型是方法的多型,屬性沒有多型性

上代碼:

? 父類:Person

package com.xiaodi.operator.oop.demo05;

public class Person {
    public void run() {
        System.out.println("run");
    }
}

? 子類:Student

package com.xiaodi.operator.oop.demo05;

public class Student extends Person{
    @Override
    public void run() {
        System.out.println("son");
    }

    public void eat() {
        System.out.println("eat");
    }
}

? 啟動程式:Application

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo05.Person;
import com.xiaodi.operator.oop.demo05.Student;

public class Application {

    public static void main(String[] args) {

        //一個物件的實際型別是確定的
        //new Student();
        //new Person();

        //可以指向的參考型別就不確定了
        Student s1 = new Student();
        Person s2 = new Student();//父類的參考指向子類
        Object s3 = new Student();
        //得出結論:一個類的實際物件型別是確定的,但是指向的參考型別可以是他的父類和Object類

        //我們現在在Person類里寫一個run方法,我們就能用s2去呼叫(輸出run);然后我們去子類重寫一下這個rum方法
        s2.run();
        s1.run();
        //兩個都輸出son(也就是說如果子類重寫了父類的方法,那么就執行子類的方法)

        //我們在子類加了一個eat方法(父類沒有):那么s2還能去呼叫這個方法嗎(s1肯定可以,因為s1就是Student型別)
        s1.eat();
        //s2.eat();  是不可以這樣去調的(因為我們的s2是Person型別的,person里沒有這個方法)
        //但是如果person里面和student里面都有的話,子類沒有重寫的情況下那么它就呼叫父類的,如果子類重寫了那么就呼叫子類的

        //得出結論:物件能執行哪些方法,主要看物件左邊的型別,和右邊關系不大
        //        Student(子類)型別能呼叫的方法都是自己的或者繼承父類的
        //        Person(父類)型別,雖然可以指向子類,但是不能呼叫子類獨有的方法

    }
}

多型小總結:注意事項(一定要把注意事項搞明白我們才能避免錯誤的發生)

  • 1、多型是方法的多型,屬性沒有多型
  • 2、必須是有父子關系 (如果沒有關系轉換的話會報一個例外:ClassCastException!)
  • 3、多型存在條件:(1)需要有繼承關系 (2)方法需要重寫 (3)父型別參考指向子類物件
    • 有些方法不能重寫:
      • 1、static 方法是屬于類的,它不屬于實體
      • 2、final 常量
      • 3、private方法是私有的也不能重寫

instanceof和 型別轉換(參考型別)

instanceof

instanceof:判斷一個物件是什么型別(有父子關系就ok,沒有就不行)

演示:

? 父類:Person

package com.xiaodi.operator.oop.demo05;

public class Person {
    public void run() {
        System.out.println("run");
    }
}

? 子類:Student

package com.xiaodi.operator.oop.demo05;

public class Student extends Person{}

? 子類:Teacher

package com.xiaodi.operator.oop.demo05;

public class Teacher extends Person {}

? 啟動程式:Application

package com.xiaodi.operator.oop;


import com.xiaodi.operator.oop.demo05.Person;
import com.xiaodi.operator.oop.demo05.Student;
import com.xiaodi.operator.oop.demo05.Teacher;

public class Application {

    public static void main(String[] args) {
        //當前的關系:Opject > Person > Student
        //當前的關系:Opject > Person > Teacher
        Object object = new Student();
        System.out.println(object instanceof Student);//ture
        System.out.println(object instanceof Person);//ture
        System.out.println(object instanceof Object);//ture
        System.out.println(object instanceof Teacher);//false
        System.out.println(object instanceof String);//false
        System.out.println("=====================");
        
        Person person = new Student();
        System.out.println(person instanceof Student);//true
        System.out.println(person instanceof Person);//true
        System.out.println(person instanceof Object);//true
        System.out.println(person instanceof Teacher);//false
        // System.out.println(person instanceof String);//編譯報錯!
        System.out.println("=====================");
        
        Student student = new Student();
        System.out.println(student instanceof Student);//true
        System.out.println(student instanceof Person);//true
        System.out.println(student instanceof Object);//true
        // System.out.println(student instanceof Teacher);//編譯報錯!
        // System.out.println(student instanceof String);//編譯報錯!

    }
}

得出結論:System.out.println(x instanceof y);

  • 能不能編譯通過主要看x的參考型別跟y是否存在父子關系(如果存在編譯通過,如果不存在編譯不通過)
  • 而結果主要看x指向的實際型別是不是y的子型別(就是說x指向的型別跟y有關系就為true)

型別轉換

? 父類:Person

package com.xiaodi.operator.oop.demo05;

public class Person {
    public void run() {
        System.out.println("run");
    }
}

? 子類:Student

package com.xiaodi.operator.oop.demo05;

public class Student extends Person{
    public void go() {
        System.out.println("go");
    }
}

? 啟動程式:Application

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo05.Person;
import com.xiaodi.operator.oop.demo05.Student;

public class Application {
    public static void main(String[] args) {
        //現在我們知道Student里面能用兩個方法,一個是go,一個是繼承過來的run
        //型別之間的轉換 :父(高) 子(低)
        //低轉高 (子類轉換為父類:可能丟失自己本來的一些方法!)
        Student student = new Student();
        Person ps = student;
        ps.run();

        Person person = new Student();
        //我們這邊person.go();是會報錯的,如果我們想讓他執行就要進行型別轉換
        //高轉低(強制轉換)Person型別轉換成Student型別
        Student person1 = (Student) person;
        person1.go();
        //和成一句代碼就是象下面這樣
        ((Student) person).go();

    }
}

多型總結:

  • 1、父類參考指向子類的物件
  • 2、把子類轉換為父類,向上轉向
  • 3、把父類轉換為子類,向下轉型;強制轉換
  • 4、方便方法的呼叫,減少重復的代碼!使代碼變簡潔!

這些大家可能會很懵,都是一些理論知識,每個人的理解能力不一樣,知道怎么用就行,等后面用到了,你自然就懂了,后面自己慢慢悟,別著急!別著急!別著急!


static關鍵字詳解

static:加在屬性上叫靜態屬性,加在方法上叫靜態屬性

package com.xiaodi.operator.oop.demo06;

public class Student {
    private static int age; //靜態屬性
    private double score; //非靜態屬性

    public void run() {} //非靜態方法

    public static void go() {} //靜態方法
    
    public static void main(String[] args) {
        Student s1 = new Student();

        System.out.println(Student.age);//通過類呼叫
        System.out.println(age);//跟上面的效果一樣
        //System.out.println(score);//非靜態屬性會報錯
        System.out.println(s1.age);//通過物件呼叫
        System.out.println(s1.score);//通過物件呼叫

        Student.go();
        go();
        s1.go();
        s1.run();
    }
}

? 一個類里面的靜態屬性或方法在記憶體中是和類一起加載的,能通過類呼叫(在本類中甚至能直接寫);非靜態的則需要通過new

代碼塊(補充)

package com.xiaodi.operator.oop.demo06;

public class Person {
    //匿名代碼塊
    {
        System.out.println("匿名代碼塊");
    }

    //靜態代碼塊
    static {
        System.out.println("靜態代碼塊");
    }

    //構造器

    public Person() {
        System.out.println("構造方法");
    }

    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println();
        Person person2 = new Person();
    }
}

執行結果:

? 靜態代碼塊
? 匿名代碼塊
? 構造方法

? 匿名代碼塊
? 構造方法

通過執行結果我們發現:靜態代碼塊最優先,其次才是匿名代碼塊,最后才執行構造方法,且靜態代碼塊只執行一次

匿名代碼塊我們一般用來賦一些初始值

靜態匯入包(一般人很少這么玩,知道有這個東西就行)

package com.xiaodi.operator.oop.demo06;

//import java.lang.Math.random; 匯入java.lang下面的Math類下面的random方法,這樣是會報錯的,需要加上靜態
import static java.lang.Math.random;

public class Test {

    public static void main(String[] args) {
        //生成亂數:Math.random
        System.out.println(Math.random()); //這樣呼叫是不是很麻煩,我們把方法導進來
        System.out.println(random());//導進來之后就能這樣寫
    }
}

主要說一下:通過final修飾的類就不能被繼承了(意思就是斷子絕孫了哈哈哈)


抽象類和介面

抽象類

  • abstract修飾符可以用來修飾方法也可以用來修飾類,如果修飾方法,那么該方法就是抽象方法;如果修飾類,那么該類就是抽象類

  • 抽象類中可以沒有抽象方法,但是有抽象方法的類一定要宣告為抽象類

  • 抽象類,不能使用new關鍵字來創建物件,它是用來讓子類繼承的,

  • 抽象方法,只有方法的宣告,沒有方法的實作,它是用來讓子類實作的,

  • 子類繼承抽象類,那么就必須要實作抽象類沒有實作的抽象方法,否則該子類也要宣告為抽象類

? 父類:Action

package com.xiaodi.operator.oop.demo07;

//abstract 抽象類
public abstract class Action {

    //abstract 抽象方法,只有方法的名字,沒有方法的實作 (約束,讓別人幫我們實作)
    public abstract void doSomething();

    //抽象類的特點:
        //不能new這個抽象類,只能靠子類去實作它:約束!
        //只能去new它的子類,如果它的子類沒實作,只能去new它的子子類

        //抽象類里面可以寫普通方法
        //抽象方法必須在抽象類中

    //思考?
    //       抽象類既然不能new,那么存在構造器嗎?(大家自己打開class編譯看一下)
    //       抽象類存在的意義? (提高開發效率)

}

? 子類:A

package com.xiaodi.operator.oop.demo07;

//抽象類的所有方法,繼承它的子類,都必須要重寫去實作他的方法,除非它的子類也是抽象類
//抽象類extends:單繼承,有局限性,(介面可以多繼承)
public class A extends Action{
    @Override
    public void doSomething() {
        System.out.println("doSomething");
    }
}

抽象類并不是我們的重點,了解一下就好了;下面的介面跟抽象類非常像用的人也比較多(介面可多繼承)

介面

  • 普通類:只有具體實作

  • 抽象類:具體實作和規范(抽象方法)都有! 業余約束!

  • 介面:只有規范!自己無法寫方法~專業的約束! 能干約束和實作分離:面向介面編程

  • 介面就是規范,定義的是一組規則,體現了現實世界中“如果你是...則必須能...”的思想,如果你是天使,則必須能飛,如果你是汽車,則必須能跑,如果你是好人,則必須干掉壞人;如果你是壞人,則必須欺負好人,

  • 介面本質是契約,就像我們人間的法律一樣,制定好后大家都遵守,

  • OO的精髓,是對物件的抽象,最能體現這一點的就是介面,為什么我們討論設計 模式都只針對具備了抽象能力的語言(比如c++、java、c#等),就是因為設計模式所研究的,實際上就是如何合理的去抽象,

宣告類的關鍵字是class,宣告介面的關鍵字是interface

? 介面:UserService

package com.xiaodi.operator.oop.demo08;

//interface 定義的關鍵字  介面都需要有實作類
public interface UserService {
    //介面中的所有定義其實都是抽象的

    //屬性默認的是一個靜態常量 public static final
    int age = 99; //一般不會這么玩

    //  public abstract void add(String name);//假設方法修飾符你不寫默認就是public abstract
    //所以介面都可以像下面這樣去寫 回傳值型別 方法的名字([引數可選]);
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}

? 介面:TimeService

package com.xiaodi.operator.oop.demo08;

public interface TimeService {
    void timer();
}

? 介面的實作:UserServiceImpl

package com.xiaodi.operator.oop.demo08;

//實作類名一般加一個Impl就行
//implements 介面實作類關鍵字  (從側面實作了我們的多繼承)
public class UserServiceImpl implements UserService,TimeService{
    //如果你要去實作介面里面的所有定義,你必須要去重寫里面的所有方法

    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {

    }
}

介面的點作用:

  • 1、約束
  • 2、定義一些方法,讓不同的人實作(比如你有10個員工,但是他們都會去完成一份共同的作業,10個人實作的是一個介面,但是有10種不同是實作方式)
  • 3、方法都是:public abstract 屬性都是:public static final,一般沒人會去玩屬性
  • 4、介面不能被實體化~介面中沒有構造方法
  • 5、可以通過implements實作多個介面
  • 6、實作介面必須重寫介面里面的方法

? 抽象的思想很難鍛煉 :Java誰都會對吧 那么為什么有些人能做到架構師有些人不能 (架構師就需要抽象思維非常非常好,你要把一個系統的結構全部抽象成介面,你能通過介面去定義一個系統的時候,那時你的架構能力就已經很強了,但是大部分人做不到)


內部類

  • 內部類就是在一個類的內部在定義一個類,比如,A類中定義了一個B類,那么B類相對A類來說就稱為內部類,而A類相對B類來說就是外部類,

  • 1、成員內部類

package com.xiaodi.operator.oop.demo09;

public class Outer {

    private int id = 10;
    public void out() {
        System.out.println("這是外部類的方法");
    }

    public class Inner{
        public void in() {
            System.out.println("這是內部類的方法");
        }
        //內部類訪問外部類的私有屬性
        public void getId() {
            System.out.println(id);
        }
    }
}

測驗:Application

package com.xiaodi.operator.oop;

import com.xiaodi.operator.oop.demo09.Outer;

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

        //外部類的實體化大家都懂了吧
        Outer outer = new Outer();

        //這個內部類要通過外部類來實體化
        Outer.Inner inner = outer.new Inner(); //是不是非常奇葩
        inner.in();
        inner.getId();
    }
}
  • 2、靜態內部類
package com.xiaodi.operator.oop.demo09;

public class Outer {

    private int id = 10;
    public void out() {
        System.out.println("這是外部類的方法");
    }

    public static class Inner{
        public void in() {
            System.out.println("這是內部類的方法");
        }

        //外部的id就拿不到了,因為是靜態的類存在的時候就存在,那個時候id這個屬性還沒出生
    }
}
  • 3、區域內部類
package com.xiaodi.operator.oop.demo09;

public class Outer {

    //區域內部類 寫在方法里面的
    public void method() {
        class Inner {
            public void in() {
                
            }
        }
    }
}
  • 4、匿名內部類
package com.xiaodi.operator.oop.demo09;

public class Outer {
    public static void main(String[] args) {
        //我們正常實體化是像下面這樣干的
        Apple apple = new Apple();
        //匿名內部類就是沒有名字去初始化類,不用把實體保存到變數中
        new Apple().eat();

        //匿名內部類 介面的實作
        new UserService() {
            @Override
            public void hello() {

            }
        };
    }

}
class Apple{
    public void eat() {
        System.out.println("1");
    }
}

interface UserService {
    void hello();
}
  • 5、也叫內部類
package com.xiaodi.operator.oop.demo09;

public class Outer {

}
//一個java檔案中可以有多個class類,但是只能有一個public class類
class A {

}

大家這里先了解一下就可以,講內部類主要目的是讓大家知道有這個東西,以后分析原始碼看到,不要不知道這是什么東西就行

本章內容較多,建議看兩遍以上,第二遍你會發現一些第一遍不理解的,慢慢理解了

本章內容較多,建議看兩遍以上,第二遍你會發現一些第一遍不理解的,慢慢理解了

本章內容較多,建議看兩遍以上,第二遍你會發現一些第一遍不理解的,慢慢理解了

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

標籤:Java

上一篇:Tomcat高級配置(應用場景總結及示例)

下一篇:【JavaWeb-JSP】筆記匯總 --- JSP 規范;EL 運算式

標籤雲
其他(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