java基礎(六):面向對象

来源:https://www.cnblogs.com/muling1m/archive/2023/02/05/17094133.html
-Advertisement-
Play Games

面向對象 面向對象:以類的方式組織代碼,以對象組織數據 特性: 封裝 繼承 多態 類:抽象概念 對象:具體事物 面向對象是java學習的重中之重,畢竟java就是一個面向對象的語言~ 類 = 屬性+方法 面向對象的概念適合複雜系統、多人協作 從巨集觀上來說,java是面向對象的,但在微觀上是面向過程的 ...


面向對象

面向對象:以類的方式組織代碼,以對象組織數據

特性:

  1. 封裝
  2. 繼承
  3. 多態

類:抽象概念

對象:具體事物

  • 面向對象是java學習的重中之重,畢竟java就是一個面向對象的語言~
  • 類 = 屬性+方法
  • 面向對象的概念適合複雜系統、多人協作
  • 從巨集觀上來說,java是面向對象的,但在微觀上是面向過程的

創建

對象的創建

使用new實例化一個對象,如

Student student = new Student();//實例化對象

new時:

  • 記憶體空間的分配
  • 屬性的初始化
  • 構造器的調用
  • 返回一個對象的引用(指針)

構造器

構造器在實例化時首先被自動調用,用於初始化參數。

new的本質是調用了構造器,返回一個對象

  • 名字和類名相同

  • 沒有返回類型(不能寫!)

  • 可以傳參

  • this是一個指針,指向這個對象本身

    public class Person {
        String name;
        public Person(){
            //構造器
            this.name = "小明";
        }
    
    }
    

封裝--訪問控制

“高耦合,低內聚”,內部數據操作細節自己完成,不由外部干涉, 暴露少部分方法給外部使用。

封裝:禁止訪問對象的實際表示,而應該通過介面來訪問。

修飾詞:

  • public:可以由外部調用,公開使用
  • private:不可由外部調用
  • protected:由本包內或不同包的子類調用

繼承

使用extend關鍵字,表示子類是父類的擴展

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

  • 子類擁有父類的全部public/protected方法和屬性
  • 且子類可以對所有方法和屬性重寫
  • private屬性無法被繼承
  • java中所有類都是object類的子類

構造器

使用super可以訪問到父類,構造器中super.generator()可以調用父類的構造器。

public class Person {
    String name;

    public Person(String name){
        //構造器
        this.name = name;
    }

}
public class Student extends Person{
    Student(String name){
        super(name);
    }
}
public class Demo2 {

    public static void main(String[] args){
        Student s = new Student("小明");
        System.out.println(s.name);
    }
}

輸出“小明”。

如果在子類中不指定調用super,會自動調用

public class Person {
    String name;
    public Person() {
        //構造器
        System.out.println("父類Person無參數構造器執行");
    }
}
public class Student extends Person{
    Student(){
        System.out.println("子類Student無參數構造器執行");
    }
}

在new Student時輸出:

若將子類構造器改為有參,仍然會首先調用父類的無參構造器

大致邏輯如下:

註:

  • 調用構造器時,需要將父類構造器調用語句放在子類構造器的第一句
  • 父類沒寫無參,預設有一個空的構造器函數
  • 如果寫了一個有參構造器,那麼父類就沒有無參構造器了,子類不能自動調用構造器,即子類中必須顯式調用有參構造器了。

方法重寫

  1. Person類:
public static void test(){
        System.out.println("Person Test");
    }

Student類:

public static void test(){
        System.out.println("Student Test");
    }

調用:

public static void main(String[] args){
        Student s = new Student("小明");
        s.test();
    }

結果:

  1. 但是,如果修改main
public static void main(String[] args){
        Person s = new Student("小明");
        s.test();
    }

會導致輸出:

這可以說明

  • 調用的方法根據聲明的類型確定
  1. 以上結論來自於靜態方法

    如果全部改為非靜態,即將test改為無static修飾

     @Override
        public  void test(){
            System.out.println("Student Test");
        }
    

註意點:

  • override 的前提是繼承
  • 方法名相同
  • 參數列表相同(不是重載)
  • 修飾符的範圍只能擴大不能縮小 public>protected>default>private
  • 異常的範圍可以被縮小但不能擴大,如:ClassNotFoundException->Exception

多態

定義

同一方法根據對象的不同採用不同的行為

引用類型

一個對象的實際類型是確定的,但引用類型並不一致

Student s = new Student();
Person s1 = new Student();
Object s2 = new Student();

實際類型都是Student,而引用類型可以是其任意父類

對於這樣的對象s1/s2,如果沒有static修飾,調用一個方法時

  1. 若子類父類都有該方法,且子類未重寫:調用父類的方法

  2. 若都有,但子類重寫了:調用子類的方法

  3. 若只有子類有,則無法調用(需要強制類型轉換修改引用類型)

    如在Student寫一個新的eat方法:

即能調用的方法取決於其引用類型而不是實際類型

方法修飾

  1. static 屬於類,不屬於對象,不可重寫

  2. final 無法修改,不可重寫

  3. private 只屬於父類,無法重寫

instanceof操作符

語法:

obj instanceof class
System.out.println(s instanceof Student);//true
        System.out.println(s1 instanceof Student);//true
        System.out.println(s1 instanceof Object);//true
        System.out.println(s2 instanceof Student);//true
        System.out.println(s2 instanceof Teacher);//false

如果對象的類是class或class的子類,則為True

在編譯狀態中,class可以是object對象的父類,自身類,子類。在這三種情況下Java編譯時不會報錯。(需要在同一條繼承鏈上)

在運行轉態中,class可以是object對象的父類,自身類,不能是子類。在前兩種情況下result的結果為true,最後一種為false。但是class為子類時編譯不會報錯。運行結果為false。

編譯的時候查看其引用類型判斷是否報錯。

運行的時候查看其實際類型判斷是否為true。

強制類型轉換

優先順序:父類>子類。

子類轉父類自動轉換。

父類轉子類需要強制轉換。

轉父類後部分方法可能無法再調用。


static

  • static修飾(靜態)的從屬於類,普通的從屬於對象

  • 靜態方法不能調用非靜態成員

變數

靜態變數(類變數)

  • 有static修飾的變數為靜態變數,在該類的記憶體中只能存在一個,可以使用類名.變數名進行訪問
  • 內部任何方法都可以直接訪問靜態變數(可以不使用類名.靜態成員進行訪問)
  • 類外部可以使用類名訪問類中靜態變數

實例變數

  • 無static修飾的變數

  • 每創建一個實例就會生成一個新的記憶體空間

  • 類內部只有非靜態方法可以訪問實例變數

  • 靜態方法或其他類中只能通過實例對象訪問

靜態變數的作用

  • 靜態變數被所有實例共用,可以作為實例對象間的共用數據
  • 如果所有實例都有一個相同的常量屬性,可以定義為static以節省空間

方法

靜態方法(類方法)

  • 靜態方法不需要通過任何實例就可以被調用,
  • 不能使用this/super關鍵字
  • 也不能直接訪問類內部的實例變數和實力方法
  • 可以直接調用類內部的靜態變數和靜態方法

實例方法

  • 通過實例對象訪問

代碼塊

靜態代碼塊

  • static{}代碼塊
  • 用於初始化類(一次性的),為類的靜態變數賦初值
  • 類似於一個方法,但不在方法體中
  • 可以在類的任意位置,可以有任意多個
  • java虛擬機在載入類的時候執行靜態代碼塊
  • 多個代碼塊按順序運行
  • 靜態代碼塊和靜態方法類似,不能訪問非靜態成員

非靜態代碼塊

  • {}
  • 創建對象時自動執行,不創建對象不執行
  • 代碼域中的變數都是局部的,只在內部使用

抽象

abstract修飾

抽象類

  • abstract修飾的方法
  • 抽象類中可以有抽象方法和具體方法
  • 抽象類無法實例化

抽象方法

  • 抽象方法只聲明沒有方法體
  • 抽象方法必須在抽象類中
  • 子類重寫父類時,必須重寫父類的所有抽象方法
  • 不能用private修飾,因為private阻止重寫

實例

public abstract class Shape {
    public int width; // 幾何圖形的長
    public int height; // 幾何圖形的寬

    public Shape(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public abstract double area(); // 定義抽象方法,計算面積
}
public class Square extends Shape {
    public Square(int width, int height) {
        super(width, height);
    }

    // 重寫父類中的抽象方法,實現計算正方形面積的功能
    @Override
    public double area() {
        return width * height;
    }
}
public class Triangle extends Shape {
    public Triangle(int width, int height) {
        super(width, height);
    }

    // 重寫父類中的抽象方法,實現計算三角形面積的功能
    @Override
    public double area() {
        return 0.5 * width * height;
    }
}

介面

  • 普通類:只有具體實現
  • 抽象類:有具體實現和規範(抽象方法)
  • 介面:只有規範,沒有具體實現 專業的約束,實現約束和實現的分離,比抽象類更加抽象

介面定義

[public] interface interface_name [extends interface1_name[, interface2_name,…]] {
    // 介面體,其中可以包含定義常量和聲明方法
    [public] [static] [final] type constant_name = value;    // 定義常量
    [public] [abstract] returnType method_name(parameter_list);    // 聲明方法
}
  • 介面只能繼承介面
  • public定義的介面可以被任何類使用,而沒有public只能被包內使用
  • 介面中的變數隱式聲明為public static final(可以不寫),即為常量,所以全部必須初始化
  • 介面中的方法隱式聲明為 public abstract

介面實現

  • 一個類可以實現一個或者多個介面

  • 實現使用implements關鍵字

    <public> class <class_name> [extends superclass_name] [implements interface1_name[, interface2_name…]] {
        // 主體
    }
    
  • 與繼承類似,可以獲得所有的常量和方法

  • implements在extend後

  • 類實現介面後必須重寫所有抽象方法

public interface IMath {
    public int sum();    // 完成兩個數的相加
    public int maxNum(int a,int b);    // 獲取較大的數
}
public class MathClass implements IMath {
    private int num1;    // 第 1 個操作數
    private int num2;    // 第 2 個操作數
    public MathClass(int num1,int num2) {
        // 構造方法
        this.num1 = num1;
        this.num2 = num2;
    }
    // 實現介面中的求和方法
    public int sum() {
        return num1 + num2;
    }
    // 實現介面中的獲取較大數的方法
    public int maxNum(int a,int b) {
        if(a >= b) {
            return a;
        } else {
            return b;
        }
    }
}

內部類

類內部定義的類

分類:

  1. 成員內部類
  2. 靜態內部類
  3. 局部內部類
  4. 匿名內部類
  • 內部類還是一個獨立的類,會編譯為獨立的.class文件,但前面會冠以類名和$符號
  • 是內部類的一個成員,可以操作到外部類的私有屬性
  • 外部類只有兩種級別:public和預設
  • 內部類有四種級別:public、protected、private、預設
Outer o = new Outer();
//外部類可直接new
Inner in = new Inner();
//外部類外需要通過外部類來實例化內部類
Outer.Inner inner = o.new Inner();

實例內部類

沒有static修飾,也成為非靜態內部類,例:

public class Outer {
    class Inner {
        // 實例內部類
    }
}
  • 和實例方法、實例變數相同,在外部類/外部類以外,必須通過外部類的實例創建內部類的實例
  • 實例內部類中可以訪問外部類的所有成員(多層嵌套也可)
  • 外部類中不能直接訪問內部類的成員,而必須通過內部類的實例訪問(不是很懂)
  • 實例內部類中的成員不能使用static修飾,除非同時有final修飾

靜態內部類

static修飾的內部類,例:

public class Outer {
    static class Inner {
        // 靜態內部類
    }
}
  • 可以通過外部類創建內部類的實例
  • 類中可定義靜態成員/實例成員
  • 可直接訪問外部類的靜態成員,如果要訪問外部類的實例成員,則需要通過外部類的實例去訪問。

局部內部類

一個方法中定義的類,如:

public class Test {
    public void method() {
        class Inner {
            // 局部內部類
        }
    }
}
  • 類似局部變數,不用訪問控制修飾符和static修飾符修飾
  • 只在方法內可用
  • 不能定義static成員
  • 內部類的內部類也不能用訪問控制修飾符和static修飾符
  • 可訪問外部類的所有成員
  • 方法中的成員與外部類成員同名,可以使用 .this. 的形式訪問外部類中的成員。

匿名內部類

沒有類名的內部類,直接使用new來聲明,例:

new <類或介面>() {
    // 類的主體
};

一般用法:

  • 繼承一個類,重寫其方法。
  • 實現一個介面(可以是多個),實現其方法。
public class Out {
    void show() {
        System.out.println("調用 Out 類的 show() 方法");
    }
}
public class TestAnonymousInterClass {
    // 在這個方法中構造一個匿名內部類
    private void show() {
        Out anonyInter = new Out() {
            // 獲取匿名內部類的實例
            void show() {
                System.out.println("調用匿名類中的 show() 方法");
            }
        };
        anonyInter.show();
    }
    public static void main(String[] args) {
        TestAnonymousInterClass test = new TestAnonymousInterClass();
        test.show();
    }
}
  • 和局部內部類相同,可訪問外部類所有成員。若位於方法中,只能訪問方法中final修飾的量
  • 可以使用非靜態代碼塊進行初始化,在父類的構造函數後執行

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Docker部署SpringBoot項目 前言: 以前幾次在雲伺服器上部署項目都是手動打包,安裝mysql等環境最後再部署運行,相對比較麻煩而且加上網上各種教程質量層次不齊,如果過程中出錯的話排查問題對於新人來說已經夠喝一壺了。(我自己第一次手動裝mysql8.0就出過問題,最後找不到問題所在只能推 ...
  • Git for Windows 的 Bash 有一個很實用的功能,如果當前目錄處於 Git 倉庫中,那麼命令行中會顯示當前 Git 分支的名稱(見下圖)。 然而原版的 MSYS2 Bash 沒有這個功能(見下圖),不過我們可以自己動手配置出相同的效果。 配置方法 打開 MSYS2 的家目錄,找到 . ...
  • 一:背景 1. 講故事 上一篇寫完 SQLSERVER 的四個事務隔離級別到底怎麼理解? 之後,有朋友留言問什麼時候可以把 snapshot 隔離級別給補上,這篇就來安排,快照隔離級別看起來很魔法,不過在修車之前,得先看下怎麼開車。 二:snapshot 隔離詳解 1. snapshot 之前的困境 ...
  • 洛谷oj題單【入門2】分支結構-入門難度(Java) 來源:https://www.luogu.com.cn/training/101#problems P5709 【深基2.習6】Apples Prologue / 蘋果和蟲子 import java.util.Scanner; public cl ...
  • 以下內容為本人的學習筆記,如需要轉載,請聲明原文鏈接 微信公眾號「ENG八戒」https://mp.weixin.qq.com/s/B1hH5Qzd2RkAiiUId1tLWw 本文大概 2874 個字,閱讀需花 10 分鐘 內容不多,但也花了一些精力 如要交流,歡迎關註我然後評論區留言 謝謝你的點 ...
  • odoo菜單定義和修改學習總結 環境 odoo-14.0.post20221212.tar 定義菜單 方式1: <?xml version="1.0"?> <odoo> <menuitem id="root_menu_id" name="TopMenu" web_icon="estate,stati ...
  • REST和SpringMVC映射請求數據 7.REST-優雅的url請求風格 7.1REST基本介紹 REST風格詳細介紹 REST:即 Representational State Transfer,表述性狀態傳遞。它結構清晰,同時可以隱藏行為。 通過一個url來直觀展示傳統風格與REST風格的區 ...
  • @RequestMapping 1.基本使用 @RequestMapping註解可以指定 控制器(處理器) 的某個方法的請求url 2.@RequestMapping其他使用方式 2.1修飾方法和類 @RequestMapping註解可以修飾方法,還可以修飾類。 當同時修飾類和方法時,請求的url就 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...