Java學習-第一部分-第二階段-第六節:泛型

来源:https://www.cnblogs.com/wenjie2000/archive/2022/08/29/16637815.html
-Advertisement-
Play Games

泛型 筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 泛型的理解和好處 看一個需求 請編寫程式,在ArrayList中,添加3個Dog對象 Dog對象含有name和age,並輸出name和age(要求使用getXxx()) 先使用傳 ...


泛型

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

泛型的理解和好處

看一個需求

  1. 請編寫程式,在ArrayList中,添加3個Dog對象

  2. Dog對象含有name和age,並輸出name和age(要求使用getXxx())

先使用傳統的方法來解決->引出泛型

public static void main(String[] args) {
    ArrayList arrayList = new ArrayList();
    arrayList.add(new Dog("旺財", 10));
    arrayList.add(new Dog("發財", 1));
    arrayList.add(new Dog("小黃",5));
    //假如我們的程員,不小心,添加了一隻貓
    arrayList.add(new Cat("招財貓",8));
    //遍歷
    for (Object o : arrayList) {
        //向下轉型0bject ->Dog
        Dog dog = (Dog)o;
        System.out.println(dog.getName() + "-" + dog.getAge());
    }
}

使用傳統方法的問題分析

  1. 不能對加入到集合ArrayList中的數據類型進行約束(不安全)
  2. 遍歷的時候,需要進行類型轉換,如果集合中的數據量較大,對效率有影響

泛型快速體驗險-用泛型來解決前面的問題

看演示

ArrayList<Dog> arrayList = new ArrayList<Dog>();

import java.util.ArrayList;
public class Test {
    public static void main(String[] args) {
        //使用傳統的方法來解決===>使用泛型
        // 解讀
        //1.當我們ArrayList<Dog>表示存放到 ArrayList集合中的元素是Dog類型〔細節後面說...)
        // 2。如果編譯器發現添加的類型,不滿足要求,就會報錯
        //3。在遍歷的時候,可以直接取出 g類型而不是 Object
        ArrayList<Dog> arrayList = new ArrayList<Dog>();
        arrayList.add(new Dog("旺財", 10));
        arrayList.add(new Dog("發財", 1));
        arrayList.add(new Dog("小黃", 5));
        //假如我們的程式員,不小心,添加了一隻貓
        // arrayList.add(new Cat("招財貓",8));//加入Dog類型外的對象會報錯,編譯不通過
        System.out.println("===使用泛科===");
        for (Dog dog : arrayList) {
            System.out.println(dog.getName() + "-" + dog.getAge());
        }
    }
}

class Dog {
    public String name;
    public int age;
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    @Override
    public String toString() {
        return "Dog [name=" + name + ". age=" + age + "]";
    }
}

泛型的好處

  1. 編譯時,檢查添加元素的類型,提高了安全性

  2. 減少了類型轉換的次數,提高效率[說明]
    √不使用泛型
    Dog-加入->Object -取出->Dog //放入到ArrayList 會先轉成Object,在取出時,還需要轉換成Dog

    √使用泛型

    Dog -> Dog -> Dog //放入時,和取出時,不需要類型轉換,提高效率

  3. 不再提示編譯警告

泛型介紹

int a = 10;
老韓理解:泛(廣泛)型(類型)=> Integer, String,Dog

  1. 泛型又稱參數化類型,是Jdk5.0出現的新特性,解決數據類型的安全性問題

  2. 在類聲明或實例化時只要指定女好需要的具體的類型即可。

  3. Java泛型可以保證如果程式在編譯時沒有發出警告,運行時就不會產生ClassCastException異常。同時,代碼更加簡潔、健壯

  4. 泛型的作用是:可以在類聲明時通過一個標識表示類中某個屬性的類型,或者是某個方法的返回值的類型,或者是參數類型。[有點難,舉例]

public class Test {
    public static void main(String[] args) {
        Person<String> person = new Person<String>("韓順平教育");
    }
}

class Person<E> {
    E s;//E表示s的數據類型,該數據類型在定義Person對象的時候指定,即在編譯期間,就確定E是什麼類型

    public Person(E s) {//E也可以是參數類型
        this.s = s;
    }

    public E f() {//返回類型使用E
        return s;
    }
}

泛型語法

泛型的聲明

interface 介面<T>{}和class 類<K,V>{}

//比如: List , ArrayList
說明:

  1. 其中,T,K,V不代表值,而是表示類型。
  2. 任意字母都可以。常用T表示,是Type的縮寫

泛型的實例化:

要在類名後面指定類型參數的值(類型)。如:

  1. List<String> strList = new ArrayList<>();[舉例說明]
  2. Iterator<Customer> iterator = customers.iterator():

泛型使用的註意事項和細節

  1. interface List<T>{} , public class HashSet<E>{}..等等

說明:T,E只能是引用類型

看看下麵語句是否正確?:
List<Integer> list = new ArrayList<Integer>();//OK

List<int> list2 = new ArrayList<int>();//錯誤

  1. 在指定泛型具體類型後,可以傳入該類型或者其子類類型

  2. 泛型使用形式
    List<lnteger> list1 =new ArrayList<lnteger>();

    List<lnteger> list2 = new ArrayList<>(); (簡寫,推薦使用)

  3. 如果我們這樣寫List list3 = new ArrayList(); 預設給它的泛型是[<E>E就是Object]

    即:List<Object> list3 = new ArrayList<>();

自定義泛型

泛型類(難點)

基本語法

class 類名<T,R...>{//...表示可以有多個泛型成員
}

註意細節

  1. 普通成員可以使用泛型(屬性、方法)
  2. 使用泛型的數組,不能初始化
  3. 靜態方法中不能使用類的泛型
  4. 泛型類的類型,是在創建對象時確定的(因為創建對象時,需要指定確定類型)
  5. 如果在創建對象時,沒有指定類型,預設為Object
//解讀
//1. Tiger後面泛型,所以我們把 Tiger就稱為自定義泛型類
//2. T,R,M泛型的標識符,一般是單個大寫字母
//3.泛型標識符可以有多個.
//4.普通成員可以使用泛型(屬性、方法)
//5. 使用泛型的數組,不能初始化
//6. 靜態方法中不能使用類的泛型
class Tiger<T, R, M> {
    String name;
    R r;//屬性使用到泛型
    M m;
    T t;
    //因為new T[8]在編譯時就需要獲得T類型,而數組在new不能確定T的類型,就無法在記憶體開空間
    T[] ts=new T[8];//編譯不通過

    public Tiger(String name, R r, M m, T t) {
        this.name = name;
        this.r = r;
        this.m = m;
        this.t = t;
    }

    //因為靜態是和類相關的,在類增載時,對象還沒有創建
    //所以,如果靜態方法和靜態屬性使用了泛型,JVM就無法完成初始化
    static R r2;
    public static void m1(M m) {
    }
    public M getM() {
        return m;
    }
    public T getT() {
        return t;
    }
}

泛型介面

自定義泛型介面

基本語法

interface 介面名<T,R..>{
}

註意細節

  1. 介面中,靜態成員也不能使用泛型(這個和泛型類規定一樣)
  2. 泛型介面的類型,在繼承介面或者實現介面時確定
  3. 沒有指定類型,預設為Object
//演示
//在繼承介面指定泛型介面的類型
interface IA extends IUsb<String,Double>{
}

//當我們去實現IA介面時,因為IA在繼承IUsu介面時,指定了U為String R為Double
//,在實現IUsu介面的方法時,使用String替換U,是Double替換R
class AA implements IA{
    @Override
    public Double get(String s) {
        return null;
    }
    @Override
    public void hi(Double aDouble) {
    }
    @Override
    public void run(Double r1, Double r2, String u1, String u2) {
    }
}

interface IUsb<U, R> {
    int n = 10;
    //U name;不能這樣使用
    //普通方法中,可以使用介面泛型
    R get(U u);
    void hi(R r);
    void run(R r1, R r2, U u1, U u2);
    //在jdk8中,可以在介面中,使用預設方法,也是可以使用泛型
    default R method(U u) {
        return null;
    }
}

泛型方法

自定義泛型方法

基本語法

修飾符<T,R..> 返回類型 方法名(參數列表){
}

註意細節

  1. 泛型方法,可以定義在普通類中,也可以定義在泛型類

  2. 當泛型方法被調用時,類型會確定

  3. public void eat(E e){},修飾符後沒有<T,R..> eat
    方法不是泛型方法,而是使用了泛型

public class Test {
    public static void main(String[] args) {
        Car car = new Car();
        car.fly("寶馬", 100);//當調用方法時,傳入參數,編譯器,就會確定類型
        car.fly(300, 100.1);//當調用方法時,傳入參數,編譯器,就會確定類型
    }
}

//泛型方法,可以定義在普通類中,也可以定義在泛型類中
class Car {//普通類

    public void run() {//普通方法
    }

    //說明泛型方法
    //1.<T,R>就是泛型
    // 2.是提供給 fly使用的
    public <T, R> void fly(T t, R r) {//泛型方法
        System.out.println(t.getClass());//String
        System.out.println(r.getClass());//Integer
    }
}

class Fish<T, R> {//泛型類

    public void run() {//普通方法
    }

    public <U, M> void eat(U u, M m) {//泛型方法
    }

    //說明
    //1. 下麵hi方法不是泛型方法
    //2.是hi方法使用了類聲明的泛型
    public void hi(T t) {
    }

    //泛型方法,可以使用類聲明的泛型,也可以使用自己聲明泛型
    public <K> void hello(R r, K k) {
    }
}

泛型繼承和通配符

泛型的繼承和通配符說明

  1. 泛型不具備繼承性
    List<Object> list = new ArrayList<String>();//錯誤
  2. :支持任意泛型類型
  3. :支持A類以及A類的子類,規定了泛型的上限
  4. :支持A類以及A類的父類,不限於直接父類,規定了泛型的下限
//舉例
import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<Object> objects = new ArrayList<>();
        printCollection2(objects);//因為Object不是AA的子類,所以 報錯

        List<BB> bb = new ArrayList<>();
        printCollection2(bb);//因為BB是AA的子類,所以 正常

    }
    // ? extends AA 表示上限,可以接受AA或者AA子類
    public static void printCollection2(List<? extends AA> c) {
        for (Object object : c){
            System.out.println(object);
        }
    }
}
class AA{
}
class BB extends AA{

}

JUnit

為什麼需要JUnit

  1. 一個類有很多功能代碼需要測試,為了測試,就需要寫入到main方法中
  2. 如果有多個功能代碼測試,就需要來回註銷,切換很麻煩
  3. 如果可以直接運行一個方法,就方便很多,並且可以給出相關信息,就好了-> JUnit

基本介紹

  1. JUnit是一個Java語言的單元測試框架

  2. 多數Java的開發環境都已經集成了JUnit作為單元測試的工具

使用步驟

註意:使用之前程式中不能含有自定義的Test類。否則會出現衝突

第一次添加(在需要運行的方法上方添加@Test,後續步驟如下圖所示)

image

image

後續使用只需要 import該Test


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

-Advertisement-
Play Games
更多相關文章
  • 本文介紹如何基於 UNIAPP 使用 即時通訊SDK ZIM SDK 快速實現基本的消息收發功能。 1 uniapp im 即時通訊功能 方案介紹 即時通訊SDK ZIM SDK 提供瞭如下接入方案: 在此方案中,您需要通過您自己的業務系統實現以下業務邏輯: 搭建客戶端的用戶管理邏輯,並下發用戶 I ...
  • 單例模式 1 定義 保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。 2 應用時機 當一個類的實例被頻繁使用,如果重覆創建這個實例,會無端消耗資源。比如 dialog 彈窗會被全局重覆使用 業務功能本身決定了全局只能有唯一的實例。比如 redux 管理的數據,只能有唯一的一份 3 應用場景 對 ...
  • 強制更新和創建低開銷的靜態組件 點擊打開視頻講解更加詳細 強制更新 如果你發現你自己需要在 Vue 中做一次強制更新,99.9% 的情況,是你在某個地方做錯了事。 你可能還沒有留意到數組或對象的變更檢測註意事項,或者你可能依賴了一個未被 Vue 的響應式系統追蹤的狀態。 然而,如果你已經做到了上述的 ...
  • 前端埋點對於那些營銷活動的項目是必須的,它可以反應出用戶的喜好與習慣,從而讓項目的運營者們能夠調整策略優化流程提高用戶體驗從而獲取更多的$。這篇文章將實現一個Vue3版本的埋點上報插件,主要功能有 通過Vue自定義指令形式實現點擊事件上報 提供手動調用上報方法 上報每個頁面訪問人數與次數(UV,PV ...
  • 小記: 本章 主要瞭解命令式、聲明式、性能與可維護性的權衡、虛擬Dom的性能、運行時和編譯時。Vue就是通過權衡這幾種方式的優缺點進行框架設計 命令式、聲明式 對比 框架對比 命令式 聲明式 特點 只關註過程 只關註結果 優點 性能最高 心智負擔小,維護性高 優缺點 心智負擔大、維護性差 性能較高 ...
  • YSLaunchar-a1.0 模型 基本介紹 本文不考慮所有具體的實現方法,之後會有更完整第二版發出 該程式計劃使用 julia 語言編寫,目前版本(1.7)並不包含類(class),取而代之,我會使用 julia 提供的兩種結構體完成。 考慮了很久,我將會把所有版本,玩家列表使用字典的形式。 主 ...
  • 以下內容為本人的著作,如需要轉載,請聲明原文鏈接 微信公眾號「englyf」https://www.cnblogs.com/englyf/p/16637890.html 如果不是機緣巧合,當年轉到C++之後,恐怕很難再有機會還寫C的代碼。面向對象在現代coding中,就像聖經一樣,在碼農的口中自帶光 ...
  • 看《C++ Primer Plus》時整理的學習筆記,部分內容完全摘抄自《C++ Primer Plus》(第6版)中文版,Stephen Prata 著,張海龍 袁國忠譯,人民郵電出版社。只做學習記錄用途。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...