目錄
1. 包裝類
1.1 包裝類的概念
1.2?基本數據類型和對應的包裝類
1.3?裝箱和拆箱
1.4?自動裝箱和自動拆箱
1.5 練習 —— 面試題
2. 泛型
2.1 如果沒有泛型——會出現什么情況?
2.2?語法
2.3?裸類型
1.沒有寫<> 但是沒有報錯為什么?
2. 裸類型
2.4?泛型如何編譯的 —— 擦除機制
2.5?泛型的上界
1. 復雜示例
2.6?泛型方法
1. 語法
2.示例
3.復雜示例
1. 包裝類
1.1 包裝類的概念
Java 八種基本類型 所對應的 類類型
為什么要有包裝類?
在Java中,由于基本類型不是繼承自Object,為了在泛型代碼中可以支持基本類型,Java給每個基本類型都對應了一個包裝類型。
1.2?基本數據類型和對應的包裝類
除了 Integer 和 Character, 其余基本類型的包裝類都是首字母大寫
1.3?裝箱和拆箱
裝箱:把基本數據類型 變為包裝類型的過程叫做 裝箱
拆箱:把包裝類型 變為基本數據類型的過程叫做 拆箱
int i = 10;
// 裝箱操作,新建一個 Integer 類型對象,將 i 的值放入對象的某個屬性中
Integer i1 = Integer.valueOf(i);
Integer i2 = new Integer(i);
// 拆箱操作,將 Integer 對象中的值取出,放到一個基本數據類型中
int j = i1.intValue();
1.4?自動裝箱和自動拆箱
可以看到在使用過程中,裝箱和拆箱帶來不少的代碼量,所以為了減少開發者的負擔,java 提供了自動機制。
public static void main(String[] args) {int a = 10;Integer b = a;Integer c = (Integer) a;int j = b;int k = (int)b;
}
1.5 練習 —— 面試題
public static void main(String[] args) {Integer a = 100;Integer b = 100;System.out.println(a == b); // trueInteger c = 200;Integer d = 200;System.out.println(c == d); // false
}
Integer 底層實現 維護了一個數組,在 -128 到 127 之間的值直接從數組拿值,其余數字直接new一個新對象,所以出現這種情況。
2. 泛型
????????一般的類和方法,只能使用具體的類型: 要么是基本類型,要么是自定義的類。如果要編寫可以應用于多種類型的代碼,這種刻板的限制對代碼的束縛就會很大。----- 來源《Java編程思想》對泛型的介紹。泛型是在JDK1.5引入的新的語法,通俗講,泛型:就是適用于許多許多類型。
從代碼上講,就是對類型實現了化參數。
2.1 如果沒有泛型——會出現什么情況?
????????雖然在這種情況下,當前數組任何數據都可以存放,但是,更多情況下,我們還是希望他只能夠持有一種數據類型,而不是同時持有這么多類型。
所以:
泛型的主要目的:就是指定當前的容器,要持有什么類型的對象,讓編譯器去做檢查。此時,就需要把類型,作為參數傳遞。需要什么類型,就傳入什么類型。?
2.2?語法
class 泛型類名稱<類型形參列表> {// 這里可以使用類型參數
}
class ClassName<T1, T2, ..., Tn> { ?
}class 泛型類名稱<類型形參列表> extends 繼承類/* 這里可以使用類型參數 */ {// 這里可以使用類型參數
}
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
}
上述圖中代碼進行改寫如下:
class MyArray<T> {public Object[] array = ?new Object[10];public T getPos(int pos) {return (T)this.array[pos];}public void setVal(int pos,T val) {this.array[pos] = val;}
}public class TestDemo {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>();// 2myArray.setVal(0,10);myArray.setVal(1,12);int ret = myArray.getPos(1);// 3System.out.println(ret);myArray.setVal(2,"bit");// 4 報錯}
}
代碼解釋:
1. 類名后的 <T> 代表占位符,表示當前類是一個泛型類了解:
【規范】類型形參一般使用一個大寫字母表示,常用的名稱有:
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type
S, U, V 等等 - 第二、第三、第四個類型
2. 注釋2處,類型后加入 <Integer> 指定當前參數類型
3. 注釋3處,不需要進行強制類型轉換
4. 注釋4處,代碼編譯報錯,此時因為在注釋2處指定類當前的類型,此時在注釋4處,編譯器會在存放元素的時候幫助我們進行類型檢查。
注意:泛型只能接受類,所有的基本數據類型必須使用包裝類!
2.3?裸類型
1.沒有寫<> 但是沒有報錯為什么?
泛型是 JDK5 引入的,為了兼容老版本。
2. 裸類型
裸類型是一個泛型類但沒有帶著類型實參,例如? ?下面塊引用中?就是一個裸類型。
MyArray list = new MyArray();
注意:我們不要自己去使用裸類型,裸類型是為了兼容老版本的 API 保留的機制。
下面的類型擦除部分,我們也會講到編譯器是如何使用裸類型的。
2.4?泛型如何編譯的 —— 擦除機制
擦除機制 :
在編譯的過程當中,將所有的?
T?
替換為?Object?
這種機制,我們稱為:擦除機制。
Java泛型擦除機制之答疑解惑https://zhuanlan.zhihu.com/p/51452375
2.5?泛型的上界
在定義泛型類時,有時需要對傳入的類型變量做一定的約束,可以通過類型邊界來約束。
沒有指定類型邊界
E
,可以視為E extends Object
常見報錯形式:
error: type argument String is not within bounds of type-variable E
??????MyArrayList<String> l2;
??????????????????^
where E is a type-variable:
??????E extends Number declared in class MyArrayList
1. 復雜示例
// 寫一個泛型類 可以求數組最大值
class Alg<E extends Comparable<E>> {public E findMax(E[] array) {E max = array[0];for (int i = 1; i < array.length; i++) {if (max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}
public class TestGeneric {public static void main(String[] args) {Integer[] array = {1,2,3,4,5,6,7,8,10};Alg<Integer> alg = new Alg<Integer>();int a = alg.findMax(array);System.out.println(a);}
}
E
必須是實現了Comparable
接口的。
2.6?泛型方法
1. 語法
方法限定符 <類型形參列表> 返回值類型 方法名稱(形參列表) { ... }
2.示例
public class Util {//靜態的泛型方法 需要在static后用<>聲明泛型類型參數public static <E> void swap(E[] array, int i, int j) {E t = array[i];array[i] = array[j];array[j] = t;}
}
因為此處要明確是泛型 <E> ,而不是一個 E 類型
使用示例-可以類型推導
Integer[] a = { ... };
Util.swap(a, 0, 9);
String[] b = { ... };
Util.swap(b, 0, 9);
使用示例-不使用類型推導
Integer[] a = { ... };
Util.<Integer>swap(a, 0, 9);
String[] b = { ... };
Util.<String>swap(b, 0, 9);
3.復雜示例
class Alg2 {public <E extends Comparable<E>> E findMax(E[] array) {E max = array[0];for (int i = 1; i < array.length; i++) {if (max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}public class TestGeneric {public static void main(String[] args) {Integer[] array = {1,2,3,4,5,6,7,8,10};Alg2 alg2 = new Alg2();int ret = alg2.findMax(array);System.out.println(ret);}
}
E
必須是實現了Comparable
接口的。