2020年java面向對象編程oop課堂筆記

面向對象編程

1. 什麼是面向對象

  • 面向過程思想
    • 步驟清晰簡單,第一部做什麼,第二部做什麼…
    • 面向過程適合處理一些較爲簡單的問題
  • 面向對象思想
    • 物以類聚,分類的思維模式,思考問題首先會解決問題需要哪些分類,然後對這些分類進行單獨思考。最後,纔對某個分類下的細節進行面向過程的思索。
    • 面向對象適合處理複雜的問題,適合處理需要多人協作的問題。

​ 對於描述複雜的事物,爲了從宏觀上把握、從整體上合理分析,我們需要使用面向對象的思路去處理。

  • 面向對象的本質:以類的方式組織代碼,以對象的組織(封裝)數據。

  • 三大特性

    • 封裝:
    • 繼承
    • 多態

2. 類與對象的創建

一個類由n個屬性和n個方法組成

創建與初始化對象

  • 使用new關鍵字創建對象
  • 使用new關鍵字創建的時候,除了分配內存空間之外,還會給創建好的對象進行默認的初始化以及對類中構造器的調用。
  • 類中的構造器也稱爲構造方法(分爲無參構造有參構造,且無參構造在沒有主動創建構造器時,默認存在),是進行創建對象的時候必須調用的。
  • 構造器有以下特點:
    • 必須和類的名字相同
    • 必須沒有返回類型,也不能寫void
    • 構造方法中不能用return返回值,但可以用return作爲方法的結束

構造器

  1. 和類名相同,權限修飾符一般只能是public
  2. 沒有返回值

作用:

  1. new 本質在調用構造方法
  2. 初始化對象的值

注意點:

  1. 如果沒有顯式定義任何構造方法,默認調用無參構造
  2. 定義有參構造之後,必須顯式地定義無參構造

實例代碼

public class Person{

    //無參構造
    private String name;
    private  int age;

    public Person() {
        System.out.println("這是無參構造!");
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("這是有參構造:"+name+"今年"+age+"歲了。");
    }

}

class TestAre{
    public static void main(String[] args) {
        new Person();
        new Person("阿凡",20);
    }
}

3. oop小結

1.類與對象
  類是一個模板:抽象 對象是一個具體的實例
2.方法
   定義與調用
3.對象的引用
   引用類型:對象通過引用來操作
4.屬性:也叫成員變量
  默認初始值:
    數字:0 0.0
    char:u0000
    boolean:false
    引用:null
    修飾符 屬性類型 屬性名 = 屬性值!
5.對象的創建和使用
    必須使用new關鍵字創造對象,構造器
    對象的屬性 person.name
    對象的方法 person。sleep()
6.類:
    靜態的屬性  屬性
    動態的行爲  方法
    - 封裝 繼承 多態 -
   

4. 封裝

  • 該露的露,該藏的藏

    • 我們程序要追求“ 高內聚,低耦合”。
      1. 高內聚就是類的內部數據操作細節自己完成,不允許外部干涉;
      2. 低耦合:僅暴露少量的方法給外部使用。
  • 封裝

    • 禁止直接訪問某一個對象中數據的實際表示,而應通過操作接口來訪問,這稱爲信息隱蔽
  • 總言:屬性私有,get/set

實例代碼

public class Person{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age <=120 && age >= 0){
            this.age = age;
        }else{
            System.out.println("年齡不合實際");
        }
    }
}

class TestAre{
    public static void main(String[] args) {
        Person person = new Person();
        person.setAge(30);
        System.out.println(person.getAge());
    }
}

5. 繼承

  • 關鍵字extends,所有類默認繼承object類
  • 繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模。
  • java類中只有單繼承,沒有多繼承!即一個類只有一個直接父類
  • 子類繼承父類,會自動擁有父類所有public,protected,默認修飾符修飾的屬性和方法(不能繼承或重寫父類的私有成員,構造器,靜態方法,final方法)。

實例代碼

public class Person  {
    private String name;
    private char sex;
    public void say(String name,char sex){
        System.out.println("我叫"+name+",性別"+sex);
    }

}

class Man extends Person{
    public static void main(String[] args) {
        Man man = new Man();
        man.say("阿凡",'男');
    }
}

6. this和super注意點

this用法:

形式參數可以被認爲是局部變量

  1. 用this關鍵字調用成員變量,防止與局部變量名稱衝突
  2. 用this關鍵字調用該類中其他成員方法(this可以省略)
  3. 用this([參數1,參數2,…])調用該類中的構造方法:
    • 只能在構造方法中使用this調用其他構造方法,不能在成員方法中使用
    • 在構造方法中使用this調用其他構造方法的語句只能寫在第一句
    • 不能在一個類的兩個構造方法中使用this互調

super用法:

  1. 使用super來調用父類的成員變量和方法,構造方法

super.成員變量

super.成員方法

super([參數1,參數2,…])

  1. 通過super調用父類構造方法的語句只能出現在子類構造方法的第一行,並且只能出現一次

super VS this:

  • 代表的對象不同:
  • this:本身調用這個對象
  • super:代表父類對象的應用
  • 前提:
    • this:沒有繼承也可以使用
    • super:只能在繼承條件纔可以使用
  • 構造方法
    • this():本類的構造
    • super():父類的構造

注意:

  1. 在構造方法中,this與super不能同時出現

  2. static靜態方法中不能使用this和super

  3. super可以調用父類的靜態方法

實例代碼

//person類
public class Person  {
    private String name = "person";

    public void print(){
        System.out.println("阿凡person");
    }
}
//student類  繼承  person類
class Student extends Person{
    private String name = "阿凡student";
    public void test1(){
        print();  //阿凡student
        test();   //阿凡person
        super.print();  //阿凡person
    }
    public void test(){
        System.out.println(name);   //阿凡student
        super.print();    //阿凡person
    }
    public void print(){
        System.out.println(this.name);
    }
}
//測試類
class TestAre{
    public static void main(String[] args) {
        new Student().test();
        new Student().test1();
    }
}

7. 重寫

重寫:需要有繼承關係,子類重寫父類的方法!

  1. 方法名、參數列表、返回值類型必須相同
  2. 子類重寫父類方法時,不能使用比父類被重寫的方法更嚴格的訪問權限

修飾符訪問權限大小:public>protected>default>private

  1. 拋出的異常:範圍可以被縮小,但不能擴大:

classNotFoundException(小) -->Exception(大)

爲什麼需要重寫:

  1. 父類的功能,子類不一定需要,或者不一定滿足!
  2. Alt + Insert : @override
//person類
public class Person  {
  private String name = "阿凡公民";
  public void print(){
      System.out.println(name+"去上班!!");
  }
}


//student類 繼承與 person類
class Student extends Person{
  private String name = "阿凡同學";
  @Override
  public void print(){  //重寫print方法
      System.out.println(name+"去上學!!");
  }
}

class TestAre{
    public static void main(String[] args) {
        new Student().print();  //阿凡同學去上學!!
    }
}

8. 多態

定義:不同類的對象在調用同一方法時所呈現出的多種不同行爲。

優點:提高了程序的可拓展性和可維護性。

  • 多態一般在接口被實現或類被繼承時使用

  • 對象的類型轉換:

    • 父類引用子類對象時**(向上轉型),不能通過父類變量去調用子類特有方法**
    • 將父類引用對象強制轉換爲子類時**(向下轉型)**,儘量用instanceof判斷一個對象是否是某個類(或接口)的實例或子類對象。

    對象 instanceof 類(或接口)

instanceof 用來測試一個對象是否爲一個類的實例
boolean result = obj instanceof class
注意點:
  1. obj必須爲引用類型,不能爲基本類型
  2. obj可以爲null
  3. obj可以爲class類的直接或間接子類
  4. obj可以爲class接口的實現類

實例代碼

//Person類
public abstract class Person {
    public abstract void work();
}
//老師類繼承Person類
class Teacher extends Person{
    @Override
    public void work() {
        System.out.println("老師上課");
    }
    //老師特有方法
    public void write(){
        System.out.println("老師寫教案");
    }
}
//醫生類繼承Person類
class Doctor extends Person{
    @Override
    public void work() {
        System.out.println("醫生看病");
    }
    //醫生特有方法
    public void operation(){
        System.out.println("醫生做手術");
    }
}
//測試類
class Test{
    public static void main(String[] args) {
        Person p1 = new Teacher();
        Person p2 = new Doctor();
        p1.work();  //老師上課
        p2.work();  //醫生看病
        if( p1 instanceof Teacher){  //判斷p1是否是Teacher類的對象
            Teacher teacher = (Teacher)p1;
            teacher.write(); //老師寫教案
        }
        else{
            Doctor doctor = (Doctor)p2;
            doctor.operation();
        }
    }
}

9. final關鍵字

final關鍵字可以修飾類、變量、方法:

  1. final修飾的類不能被繼承

  2. final修飾的方法不能被子類重寫

  3. final修飾的變量(成員變量局部變量)是常量,只能被賦值一次

    注意:

    成員變量被final修飾時,聲明變量的同時必須初始化賦值

    局部變量被final修飾時,可以先聲明,再賦值一次

10. static關鍵字

static用於修飾類的屬性,方法,代碼塊等,稱爲靜態Xxx

static只能修飾成員變量,不能修飾局部變量

注意點:

  • 靜態變量(也叫全局變量)可以被該類的所有實例對象共享

類名.變量名

  • 在同一類中,成員方法可以直接調用靜態方法,但是靜態方法不能直接調用成員方法,必須創建對象後才能訪問成員方法

類名.靜態方法();

或者

實例對象名.靜態方法();

  • 靜態代碼塊在類第一次被new 對象 實例化後纔會被執行,且只會執行一次,一般用來加載初始化信息。

static{

}

**static和final同時使用 **

  1. static final用來修飾成員變量和成員方法,可簡單理解爲“全局常量”!

  2. 對於變量,表示一旦給值就不可修改,並且通過類名可以訪問。

  3. 對於方法,表示不可覆蓋,並且可以通過類名直接訪問。

實例代碼

class Student{
    private  static int age;
    private double score;

    public static void main(String[] args) {
        Student s1 = new Student();
        System.out.println(Student.age);
        System.out.println(s1.age);
        System.out.println(s1.score);
    }
}

靜態代碼塊

實例代碼

public class Person {
    //賦初始值
    {
        System.out.println("匿名代碼塊");
    }
    //只執行一次
    static{
        System.out.println("靜態代碼塊");
    }

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

    public static void main(String[] args) {
        new Person();
    }

}

11. 抽象類

  • 關鍵字:abstract 抽象類,屬於類 單繼承 (接口是多繼承)
  • abstract修飾的抽象方法只有方法名字,沒有方法的實現!
  • 注意點
    • 抽象類中的成員變量定義沒有要求
    • 包含抽象方法的類必須定義爲抽象類
    • 抽象類不能new出來,只能靠子類實現
    • 抽象類中可以寫普通方法,包括靜態方法
    • 抽象方法必須寫在抽象類中,但抽象類可以沒有抽象方法

12. 接口

接口:只有規範,比抽象類更嚴格,是抽象類的特殊形式

public interface 接口名{

}

作用

  1. 接口裏面定義的成員變量都是 public static final修飾,只能是常量,必須賦初始值
  2. 接口中的成員方法只能是抽象方法。默認修飾符 public abstract,但public abstract可以省略不寫。
  3. 注意:接口不可以有構造方法,但抽象類可以
  4. 接口不能實例化,接口中沒有構造方法,其他類使用implements 可以實現多個接口,
  5. 必須要重寫接口中的所有方法
  6. 接口中的成員方法權限只能且都是public
  7. 接口是多繼承

實例代碼

public interface Animal {
    void shout(String name);
}

class Cat implements Animal{

    @Override
    public void shout(String name) {
        System.out.println(name + "在喵喵叫!");
    }
}

class Dog implements Animal{
    @Override
    public void shout(String name) {
        System.out.println(name+"在汪汪叫!");
    }
}

class AnimalTest{
    public static void main(String[] args) {
        Animal a1 = new Cat();
        Animal a2 = new Dog();
        a1.shout("貓");
        a2.shout("狗");
    }
}

13. 4種內部類

非常重要內部類不能有靜態方法或屬性。

成員內部類

外部類名 對象名 = new 外部類名();

外部類名.內部類名 變量名 = new 外部類名().內部類名();

注意:

  • 在成員內部類中,內部類可以直接(不用new 外部類創建對象)調用外部類的所有屬性+方法(包括靜態和非靜態)。
  • 在外部類中,不可以直接調用內部類中的屬性+方法,但可以創建內部類對象後調用。

實例代碼

//person類  外部類
public class Person {
    
    String name = "Afan";
    int age = 20;
    
    public void doSomething(){
        System.out.println("AFan在喫飯!");
    }
    public void say(){
        Heart heart = new Heart();
        heart.fleed();
        System.out.println("AFan說你好!");
    }

    //心臟 成員內部類
    class Heart{
        
        public void jump(){
            System.out.println("心臟跳動!!");
            doSomething();//直接調用外部類方法
            say();
        }
        public void fleed(){
            System.out.println("血在流");
        }
    }
}

class Test{
    public static void main(String[] args) {
        Person person = new Person();
        Person.Heart heart = person.new Heart();
        heart.jump();
        heart.fleed();
    }
}

局部內部類

也叫方法內部類,在方法中定義,有效範圍只限於方法內部,等同於局部變量。

注意:

  • 局部內部類可以在new 外部類對象後調用外部類的屬性+方法
  • 局部內部類可以 直接調用 自身在外部類中所在方法裏的局部變量。
  • 只有在創建局部內部類的方法中才可以創建局部內部類的對象,並調用內部類的所有屬性+方法。

實例代碼

/person類
public class Person {
    String name = "Afan";
    int age = 20;
    
    public void doSomething(){
        System.out.println("AFan在喫飯!");
    }
    public void say(){
        System.out.println("AFan說你好!");
    }

    public void produce(){
        
        String product_name = "電腦";
        //產品類 局部內部類
        class Production{
           // String product_name = "電腦";
            public void use(){
                Person person = new Person();  //外部類對象
                person.doSomething();
                System.out.println(product_name+"的使用");
            }
        }
        Production production = new Production();
        production.use();
    }
}

class Test{
    public static void main(String[] args) {
        Person person = new Person();
        person.produce();

    }
}

靜態內部類

本質:使用static關鍵字修飾的成員內部類

  • 靜態內部類只能直接調用外部類中的靜態屬性和靜態方法
  • 其他類需要調用靜態內部類的屬性和方法時,可以跳過外部類,直接new 內部類對象來訪問其成員。

外部類名.靜態內部類名 對象名 = new 外部類名.靜態內部類名();

實例代碼

//person類
public class Person {
    static String name = "Afan";

    public static void doSomething(){
        System.out.println("AFan在喫飯!");
    }
    public void say(){
        System.out.println("AFan說你好!");
    }

    //心臟類 就在成員內部類前面加個static
    static class Heart{

        public  void jump(){
            doSomething();

           // Person person = new Person(); 訪問非靜態成員必須創建對象。
            //person.say();

            System.out.println(name+"的心臟在跳動!!");
        }
    }
}
class Test{
    public static void main(String[] args) {
        Person.Heart heart = new Person.Heart();
        heart.jump();
    }
}

匿名內部類

java類調用某個方法時,如果該方法的參數類型是接口類型,那麼除了傳遞一個接口的實現類,也可以使用匿名內部類實現該接口來作爲該方法的參數。(開發中常用)

[修飾符] 方法名(new 父類名或者接口名(){
    // 方法重寫
    @Override 
    public void method() {
        // 執行語句
    }
};)

實例代碼

//接口類
public interface Animal {
    void shout(String name);
}

class AnimalTest{
    String name;
    public void animalShout(Animal animal){
        animal.shout(name);
    }
    public static void main(String[] args) {

      AnimalTest a1 = new AnimalTest();
      a1.name = "貓";
      //匿名內部類
      a1.animalShout(new Animal() {
          @Override
          public void shout(String name) {
              System.out.println(name+"在叫!!!");
          }
      });
    }
}

JDK8的Lamabda表達式

使用條件:只適用於在匿名內部類中只有一個抽象方法的接口實現,簡化代碼。

([數據類型1 變量名1,數據類型2 變量名2,…]) ->{表達式主體}

注意點:

  1. 參數列表只有一個參數時可以省略”()“和變量的數據類型
  2. 表達式主體只有一條語句時,可以省略主體的大括號
  3. 表達式主體可以有return返回值,當只有一條return語句,可以省略return

實例代碼

//接口類
public interface Animal {
    void shout(String name);
}
class AnimalTest{
    String name;
    public void animalShout(Animal animal){
        animal.shout(name);
    }
    public static void main(String[] args) {

      AnimalTest a1 = new AnimalTest();
      a1.name = "小貓";
      //Lamabda表達式
      a1.animalShout(name ->
              System.out.println(name+"在叫!!!")
      );
    }
}

進一步簡化Lamabda表達式(瞭解)

使用條件:Lamabda表達式主體只有一條語句

用法:程序省略主體的大括號,用英文雙冒號“::”來引用方法和構造器

Lamabda表達式對普通方法和構造方法的引用形式

種類 對應的引用示例
類名引用普通方法 類名::類普通方法名
類名引用靜態方法 類名::類靜態方法名
對象名引用方法 對象名::實例方法名
構造器引用 類名::new

14. 異常

定義:程序在編譯、運行過程中出現的非正常狀況

  java的異常類都繼承於java.lang.Throwable類

Throwable的繼承體系

[外鏈圖片轉

  • Error類:錯誤類,比較嚴重(瞭解)
  • Exception類:異常類,程序本身可以處理,java開發中進行的異常處理都是針對Exception類及其子類

Throwable類常用方法

方法說明 功能描述
String getMessage() 返回此throwable的詳細消息字符串
void printStackTrace() 打印完整的異常信息

處理異常的兩種方式

  1. 使用try…catch語句對異常進行捕獲處理

    try{
      //可能發生異常的語句
    }catch(Exception類或其子類 e){
       e.printStackTrace(); //打印輸出異常原因
       //對捕獲的異常做相應處理
    }finally{
       //無論程序是否異常都必須執行的語句
    }
    

    實例代碼

    public class Example {
        public static void main(String[] args) {
           int result = divide(4,0);
           if(result == -1){
               System.out.println("程序出現異常");}
            else{
               System.out.println(result);   
           }
        }
        //運行結果:出現的異常:/ by zero
        //        無論程序是否異常都必須執行的finally語句
        //        程序出現異常
        
        //除法運算
        public static int divide(int a,int b){
            try{
                int result = a/b;
                return  result;
            }catch(Exception e){
                System.out.println("出現的異常:"+e.getMessage());
            }finally{
                System.out.println("無論程序是否異常都必須執行的finally語句");
            }
            return -1; //如果程序異常,返回-1
        }
    }
  2. 使用throws拋出異常,等以後再處理有可能的異常,

    [修飾符] 返回值類型 方法名([參數列表]) throws Exception{
       //方法體
       }
    

    有可能出現異常的方法加上throws關鍵字後,其他類調用它時首先要處理完異常之後才能使用該方法。

實例代碼

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

       try {
           int result = divide(4, 0);
           System.out.println(result);
       }catch(Exception e){
           System.out.println("出現異常:"+e.getMessage());
       }

    }
    //運行結果:出現異常:/ by zero

    //除法運算
    public static int divide(int a,int b) throws Exception{
        int result = a/b;
        return result;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章