【數據結構】_包裝類與泛型

目錄

1. 包裝類

1.1 基本數據類型和對應的包裝類

1.2 (自動)裝箱和(自動)拆箱

1.2.1 裝箱與拆箱

1.2.2 自動(顯式)裝箱與自動(顯式)拆箱

1.3 valueOf()方法

2. 泛型類

2.1 泛型類與Object類

2.2 泛型類語法

2.3 泛型類示例

2.4 裸類型(Raw Type)

2.5 泛型類的編譯

2.5.1 擦除機制

2.5.2 泛型類型數組的實例化

2.6 泛型的上界

2.6.1? N為接口

?2.6.2?? Number為類

3. 泛型方法

3.1 語法

3.2 泛型方法示例

3.2.1 普通類的普通泛型方法

3.2.2 普通類的靜態泛型方法


1. 包裝類

在Java中由于基本類型不是繼承自Object,為了在泛型代碼中可以支持基本類型,Java給每個基本類型都對應了一個包裝類型;

1.1 基本數據類型和對應的包裝類

基本數據類型包裝類
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

除了Integer和Character,其余基本類型的包裝類都是首字母大寫;

1.2 (自動)裝箱和(自動)拆箱

1.2.1 裝箱與拆箱

裝箱(裝包):把基本數據類型變為對應的包裝類型;

拆箱(拆包):把引用類型變為基本數據類型;

1.2.2 自動(顯式)裝箱與自動(顯式)拆箱

代碼示例1:自動裝箱與顯式裝箱:

        int a = 10;// 自動裝箱Integer val = a;System.out.println(val);// 顯式裝箱Integer val2 = Integer.valueOf(a);Integer val3 = new Integer(a);System.out.println(val2);System.out.println(val3);

?代碼示例2:自動拆箱:

        Integer val1 = 10;// 自動拆箱int a = val1;System.out.println(a);// 顯式拆箱// 拆為int類型int a2 = val1.intValue();System.out.println(a2);// 拆為double類型double a3 = val1.doubleValue();System.out.println(a3);

?注:(1)自動裝箱的底層邏輯:Integer包裝類的valueOf()方法:?

(2)自動拆箱的底層邏輯:Integer包裝類的intValue()方法:

(3)顯式拆箱時,Integer包裝類不止提供了intValue()方法,還提供了doubleValue()等方法:

可以根據所需的基本類型對應調用其方法,在上文示例中,輸出結果為:

1.3 valueOf()方法

試運行以下代碼:

        Integer a = 127;Integer b = 127;System.out.println(a==b);Integer c = 128;Integer d = 128;System.out.println(c==d);

輸出結果為:

原理注解:

(1)Integer包裝類的valueOf方法源代碼與方法內部相關量的值:

(2)方法含義:

如果i在[low, high]即[-128, 127]之間,則返回cache緩存數組中下標為i+128位置的元素:

如i=0時存儲在cache[128],i=-128時則存儲在cache[0],i=127時則存儲在cache[255];

即在緩存數組中存儲了256個數字;

在該范圍內的i調用valueOf方法調用到的是同一個元素,故而a=b;

在該范圍外的i調用valueOf方法會new Integer對象,作為引用類型,==判斷的是引用類型是否是對一個對象,故而a!=b;

2. 泛型類

一般的類和方法只能使用具體的類型:基本類型或自定義類,泛型就是適用于多種類型,即對參數實現了參數化;

2.1 泛型類與Object類

現要求實現一個不限制元素種類的數組,聯想到Object類,示例代碼如下:

class MyArray{public Object[] obj = new Object[3];public Object getPos(int pos){return obj[pos];}public void setPos(int pos,Object val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {MyArray myArray = new MyArray();myArray.setPos(0,10);myArray.setPos(1,"hello");myArray.setPos(2,10.0);double ret = myArray.getPos(2);System.out.println(ret);}
}

報錯如下:

?如要創建double類型變量對數組元素進行接收,則需要進行強轉:

double ret = (double)myArray.getPos(2);

上文設計的數組具有以下特點:

① 任何數據都可以存儲; ② 獲取數據時必須進行強制類型轉換;

這并非我們需要實現的泛型數組,通常需要實現的泛型數組需求是:存儲一種類型的數據;

泛型編程是將類型作為參數傳遞的編程方式,目的是指定當前容器后可以存放某一種類型的數據;

2.2 泛型類語法

// 泛型的一般使用方法
class 泛型類名稱<類型形參列表>{
}
class ClassName<T1,T2...Tn>{
}// 泛型類的繼承
class 泛型類名稱<類型形參列表> extends 繼承類{
}
class ClassName<T1,T2,...Tn> extends ParentClass<T1>{
}

注:① 類名后的<T>代表占位符,表示當前類是一個泛型類,

類型形參一般使用一個大寫字母表示,常用名稱有:

E表示Element,K表示Key,V表示Value,N表示Number,T表示Type;

泛型當中不能實例化一個泛型類型的數組,如:

T[] ts = new T[5];

是錯誤的;

③ 泛型類實例化的同時會指定當前泛型類的指數參數類型,如果二者沖突,就會報錯,

這也是泛型編程的一個意義所在:泛型編程在程序編譯時,存儲數據時自動進行類型檢查;?

2.3 泛型類示例

class MyArray<T>{public T[] obj = (T[])new Object[3];public T getPos(int pos){return obj[pos];}public void setObj(int pos, T val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {// 實例化對象的同時指定當前泛型類的指定參數類型// 指定參數的類型必須是引用類型,如int非法而Integer合法MyArray<Integer> myArray1 = new MyArray<Integer>();myArray1.setObj(0,10);myArray1.setObj(1,78);myArray1.setObj(2,66);double ret1= myArray1.getPos(1);System.out.println(ret1);System.out.println("-------------------");MyArray<String> myArray2 = new MyArray<String>();myArray2.setObj(0,"hello");myArray2.setObj(1,"world");myArray2.setObj(2,"java");String ret2 = myArray2.getPos(1);System.out.println(ret2);}
}

輸出結果為:

2.4 裸類型(Raw Type)

裸類型是一個泛型類但沒有帶類型實參,例如:

class MyArray<T>{public T[] obj = (T[])new Object[3];public T getPos(int pos){return obj[pos];}public void setObj(int pos, T val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {MyArray list = new MyArray();}
}

但請注意:裸類型是為了兼容老版本的API,在編程時請避免裸類型的使用;

2.5 泛型類的編譯

2.5.1 擦除機制

class MyArray<T>{public T[] obj = (T[])new Object[3];public T getPos(int pos){return obj[pos];}public void setObj(int pos, T val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<Integer>();myArray.setObj(0,85);int ret = myArray.getPos(0);System.out.println(ret);}
}

查看上文代碼的字節碼文件:

在編譯完成后,運行過程中是沒有泛型的概念的,此時所有的T都被擦除為Object,通過上述的編譯器生成的字節碼文件中是不包含泛型的類型信息的;

2.5.2 泛型類型數組的實例化

java語法規定:在實例化數組時必須提供具體的元素類型,故而不能直接實例化泛型類型數組

方法1:(上文擦除機制部分示例代碼的在泛型類中創建數組的方法):

class MyArray<E>{public E[] obj = (E[]) new Object[3];
}

但該種寫法存在問題:試運行以下代碼:

class MyArray<E>{public E[] obj = (E[]) new Object[3];public E getPos(int pos){return obj[pos];}public void setObj(int pos,E val){obj[pos]=val;}// 返回數組的方法public E[] getArray(){return obj;}
}
public class Demo1 {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<Integer>();myArray.setObj(0,10);myArray.setObj(1,85);Integer[] integers = myArray.getArray();}
}

報錯及分析如下:

在繼承與多態章節已經提到過,向下轉型是不安全的;

java的數組實現非常特殊,

此處可以理解為:jvm認為使用一個固定類型如Integer或String等等類型的對象來接收Object類型對象是不安全的;

正確代碼為:(使用反射)

class MyArray<E>{public E[] obj;public MyArray(Class<E>clazz, int capacity){// 參數為數組元素類型與容量obj = (E[])Array.newInstance(clazz, capacity);}public E getPos(int pos){return obj[pos];}public void setObj(int pos, E val){obj[pos]=val;}public E[] getArray(){return obj;}
}
public class Demo1 {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>(Integer.class,10);myArray.setObj(0,1997);myArray.setObj(1,85);Integer[] integers = myArray.getArray();}
}

但以上方法并不常用,更推薦方法2:;?

繼承與多態文章鏈接如下:

CSDN

方法2:參考java的ArrayList源碼的get方法:

對于泛型類型數組的實例化,不能直接使用泛型類型作為數組元素的類型,故而可以使用Object類結合強制類型轉換實現泛型類型數組的實例化:

class MyArray<E>{public Object[] obj = new Object[3];public E getPos(int pos){return (E)obj[pos];}public void setPos(int pos, Object val){obj[pos] = val;}
}

2.6 泛型的上界

2.6.1? <E extends N> N為接口

表示實例化對象時指定的參數類型一定已經實現了N接口;

// 寫一個泛型類求一個數組的最大值
class Alg<E extends Comparable<E>>{public E findMax(E[] array){E max=array[0];for(int i=0;i<array.length;i++){if(max.compareTo(array[i])<0){max = array[i];}}return max;}
}
public class Demo2 {public static void main(String[] args) {Alg<Integer> alg = new Alg<Integer>();Integer[] array = {1,4,2,10,9,8,17,5};System.out.println("Array is:");for(Integer x:array){System.out.print(x+" ");}System.out.println();Integer val =  alg.findMax(array);System.out.println("The max element in the array is "+val);}
}

輸出結果為:

???

?2.6.2??<E extends Number> Number為類

表示E是Number的子類或E就是Number本身;

參考Number (Java Platform SE 8 ) (oracle.com)

?Integer、Double、Long、Short等等都是Number常見的直接子類:

class A<E extends Number>{A<Number> a1 = new A<>();A<Integer> a2 = new A<>();A<Double> a3 = new A<>();// A<String> a4 = new A<>();
}

3. 泛型方法

3.1 語法

方法限定符 <類型形參列表> 返回值類型 方法名稱(形參列表){...}

3.2 泛型方法示例

3.2.1 普通類的普通泛型方法

class Alg2{public<E extends Comparable> E findMax(E[] array){E max = array[0];for(int i=0;i<array.length;i++){if(max.compareTo(array[i])<1){max=array[i];}}return max;}
}
public class Demo4 {public static void main(String[] args) {Alg2 alg2 = new Alg2();Integer[] arr = {19,9,7,85,25};System.out.println("Array is: ");for(Integer x:arr){System.out.print(x+" ");}System.out.println();Integer val = alg2.<Integer>findMax(arr);System.out.println("The max element in the array is "+val);}
}

輸出結果為:

?注:調用泛型方法時泛型類型可以省略:

 Integer val = alg2.<Integer>findMax(arr);

?上行代碼可以簡寫為:

 Integer val = alg2.findMax(arr);

編譯器會根據傳遞給泛型方法的參數arr的類型判斷E的類型;

3.2.2 普通類的靜態泛型方法

class Alg2{public static<E extends Comparable> E findMax(E[] array){E max = array[0];for(int i=0;i<array.length;i++){if(max.compareTo(array[i])<1){max=array[i];}}return max;}
}
public class Demo4 {public static void main(String[] args) {Integer[] arr2 = {19,9,7,85,25};System.out.println("Array is: ");for(Integer x:arr2){System.out.print(x+" ");}System.out.println();Integer val = Alg2.findMax(arr2);System.out.println("The max element in the array is "+val);}
}

輸出結果為:

靜態泛型方法不再依賴于類的對象存在,可以使用類名直接調用;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717852.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717852.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717852.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【深度學習筆記】計算機視覺——目標檢測和邊界框

目標檢測和邊界框 前面的章節&#xff08;例如 sec_alexnet— sec_googlenet&#xff09;介紹了各種圖像分類模型。 在圖像分類任務中&#xff0c;我們假設圖像中只有一個主要物體對象&#xff0c;我們只關注如何識別其類別。 然而&#xff0c;很多時候圖像里有多個我們感興趣…

某大型制造企業數字化轉型規劃方案(附下載)

目錄 一、項目背景和目標 二、業務現狀 1. 總體應用現狀 2. 各模塊業務問題 2.1 設計 2.2 仿真 2.3 制造 2.4 服務 2.5 管理 三、業務需求及預期效果 1. 總體業務需求 2. 各模塊業務需求 2.1 設計 2.2 仿真 2.3 制造 2.4 服務 2.5 管理 四、…

在vue中對keep-alive的理解,它是如何實現的,具體緩存的是什么?

對keep-alive的理解&#xff0c;它是如何實現的&#xff0c;具體緩存的是什么&#xff1f; &#xff08;1&#xff09;keep-alive有以下三個屬性&#xff1a;注意&#xff1a;keep-alive 包裹動態組件時&#xff0c;會緩存不活動的組件實例。主要流程 &#xff08;2&#xff09…

數字化轉型導師堅鵬:證券公司數字化營銷

證券公司數字化營銷 ——借力數字化技術實現零售業務的批量化、精準化、場景化、智能化營銷 課程背景&#xff1a; 很多證券公司存在以下問題&#xff1a; 不知道如何提升證券公司數字化營銷能力&#xff1f; 不知道證券公司如何開展數字化營銷工作&#xff1f; 不知道…

胎神游戲集第二期

延續上一期 一、海島奇胎 #include<bits/stdc.h> #include<windows.h> #include<stdio.h> #include<conio.h> #include<time.h> using namespace std; typedef BOOL (WINAPI *PROCSETCONSOLEFONT)(HANDLE, DWORD); PROCSETCONSOLEFONT SetCons…

Linux 安裝pip和換源

一 配置文檔 Linux和macOS&#xff1a; 全局配置&#xff1a;/etc/pip.conf 用戶級配置&#xff1a;~/.pip/pip.conf 或 ~/.config/pip/pip.conf 二 下載 和 安裝 # pip 安裝 wget https://bootstrap.pypa.io/get-pip.py python get-pip.py 三 查看和升級 pip -Vpython -m…

GO語言學習筆記(與Java的比較學習)(十一)

協程與通道 什么是協程 一個應用程序是運行在機器上的一個進程&#xff1b;進程是一個運行在自己內存地址空間里的獨立執行體。一個進程由一個或多個操作系統線程組成&#xff0c;這些線程其實是共享同一個內存地址空間的一起工作的執行體。 并行是一種通過使用多處理器以提…

Java虛擬機 - JVM

JVM的內存區域劃分 JVM它其實也是一個進程,進程運行的過程中,會從操作系統中申請一些資源.內存就是其中的一種.這些內存就支撐了java程序的運行.JVM從系統中申請的一大塊內存,會根據實際情況和使用用途來劃分出不同的空間,這個就是區域劃分.它一般分為 堆區, 棧區, 程序計數器…

springboot240基于Spring boot的名城小區物業管理系統

基于Spring boot的名城小區物業管理系統的設計與實現 摘要 當下&#xff0c;正處于信息化的時代&#xff0c;許多行業順應時代的變化&#xff0c;結合使用計算機技術向數字化、信息化建設邁進。以前相關行業對于物業信息的管理和控制&#xff0c;采用人工登記的方式保存相關數…

InnoDB存儲引擎對MVCC的實現

MVCC MVCC的目的 在搞清楚MVCC之前,我們要搞懂一個問題,MVCC到底解決的是什么問題? 我用一句話概括,那就是為了解決讀-寫可以一起的問題! 在我們的印象里,InnoDB可以讀讀并發,不能讀寫并發,或者寫寫并發 這是很正常的想法,因為如果讀寫并發的化,會有并發問題 而對于寫寫…

帶壓縮路徑的并查集

find帶壓縮路徑的并查集 int fa[]; void init(int _size) {for(int i0;i<_size;i){fa[i] i;} } int find(int aim) {int cur aim;while (fa[aim] ! aim){aim fa[aim];}while (fa[cur] ! cur){int tmp cur;cur fa[cur];fa[tmp] aim;}return aim; } void join(int a,in…

構建安全的REST API:OAuth2和JWT實踐

引言 大家好&#xff0c;我是小黑&#xff0c;小黑在這里跟咱們聊聊&#xff0c;為什么REST API這么重要&#xff0c;同時&#xff0c;為何OAuth2和JWT在構建安全的REST API中扮演著不可或缺的角色。 想象一下&#xff0c;咱們每天都在使用的社交媒體、在線購物、銀行服務等等…

file-upload-download

方式一 情況1&#xff1a; PostMapping("/download1")public ResponseEntity<byte[]> download1() throws Exception {// 下載文件目錄位置FileInputStream fis new FileInputStream("C:\\Users\\wsd\\Pictures\\susu.jpg");// 一次讀取bytes.leng…

Sqli-labs靶場第16關詳解[Sqli-labs-less-16]自動化注入-SQLmap工具注入

Sqli-labs-Less-16 #自動化注入-SQLmap工具注入 SQLmap用戶手冊&#xff1a;文檔介紹 - sqlmap 用戶手冊 以非交互式模式運行 --batch 當你需要以批處理模式運行 sqlmap&#xff0c;避免任何用戶干預 sqlmap 的運行&#xff0c;可以強制使用 --batch 這個開關。這樣&#xff0…

【視頻編碼\VVC】多樣化視頻編碼工具了解

除了通用編碼工具&#xff0c;VVC還針對特定特性的全景視頻、屏幕視頻開發了特定的編碼工具。 全景視頻編碼 360度全包圍視角的球面視頻。為了采用傳統的視頻編碼&#xff0c;全景視頻需要轉換為平面視頻&#xff0c;經緯度等角映射&#xff08;ERF&#xff09;、立方體映射&…

PostgreSQL操作筆記

基礎操作 數據庫相關 -- 查看所有數據庫 \l-- 切換到指定數據庫 \c 庫名-- 查看庫中所有表 \d執行SQL腳本 如果有現成的SQL腳本&#xff1a; \i 腳本路徑路徑一般需要用單引號引起來。 如果需要當場編輯一次性的SQL腳本&#xff0c;可以&#xff1a; \e執行上述命令后會進…

GC機制以及Golang的GC機制詳解

要了解Golang的GC機制,就需要了解什么事GC,以及GC有哪幾種實現方式 一.什么是GC 當一個電腦上的動態內存不再需要時&#xff0c;就應該予以釋放&#xff0c;以讓出內存&#xff0c;這種內存資源管理&#xff0c;稱為垃圾回收&#xff08;Garbage Collection&#xff09;&#x…

最長上升子序列(LIS)簡介及其例題分析

一.最長上升子序列&#xff08;LIS&#xff09;的相關知識 1.最長上升子序列&#xff08;Longest Increasing Subsequence&#xff09;&#xff0c;簡稱LIS&#xff0c;也有些情況求的是最長非降序子序列&#xff0c;二者區別就是序列中是否可以有相等的數。假設我們有一個序…

【論文筆記】Initializing Models with Larger Ones

Abstract 介紹權重選擇&#xff0c;一種通過從預訓練模型的較大模型中選擇權重子集來初始化較小模型的方法。這使得知識從預訓練的權重轉移到更小的模型。 它還可以與知識蒸餾一起使用。 權重選擇提供了一種在資源受限的環境中利用預訓練模型力量的新方法&#xff0c;希望能夠…

代碼隨想錄Day67 | 695.島嶼的最大面積 1020.飛地的數量

代碼隨想錄Day67 | 695.島嶼的最大面積 1020.飛地的數量 695.島嶼的最大面積1020.飛地的數量 695.島嶼的最大面積 文檔講解&#xff1a;代碼隨想錄 視頻講解&#xff1a; 狀態 采用bfs&#xff0c;這道題相較于之前的題變為了求島嶼的最大面積。那就說明我們每遇到一個新的島嶼…