泛型
泛型是一種未知的數據類型,當我們不知道使用什麼數據類型的時候,就可以使用泛型。也可以把他看作是一個變量,用來接受數據類型
創建集合對象的時候就會確定泛型的數據類型,此時會把數據類型作爲參數傳遞 將數據類型賦值給泛型
比如說ArrayList
集合在定義的時候,不知道集合中都會存儲什麼類型的數據,所以定義的類型使用泛型E
public class ArrayList<E>{
public boolean arr(E e){...}
public E get(int index){...}
}
此時創建集合對象ArrayList<String> list = new ArrayList<>();
的時候,會將數據類型作爲參數傳遞,也就是說將String
賦值給泛型E
,就像這樣:
public class ArrayList<String>{
public boolean arr(String e){...}
public String get(int index){...}
}
創建集合對象,不使用泛型
- 好處:
默認類型就是Object類型 可以存儲任意類型數據 - 弊端:集合不安全 會引發異常,比如說
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("abc");
list.add(123);
//使用迭代器遍歷list集合
//獲取迭代器
Iterator it = list.iterator();
//使用迭代器中的方法hasNext和next遍歷集合
while(it.hasNext()){
//因爲沒有使用泛型,所以他取出的元素是Object類型
Object obj = it.next();
System.out.println(obj);
//此時如果想用String類特有的方法,比如說.length()獲取字符串長度,不能使用
//需要使用到多態向下轉型
String s = (String)obj;
System.out.println(s.length());
}
}
運行結果見下:
創建集合對象 使用泛型
- 好處:
- 避免了類型轉換的麻煩 存的是什麼類型取出來的事就是什麼類型
- 把運行期異常(代碼運行之後會拋出的異常)提升到了編譯異常,這樣更早的發現錯誤,不至於後續改的太難受
- 弊端:
- 泛型是什麼類型就只能存儲什麼類型的數據
注意:
- 泛型不止可以修飾類,也可以修飾方法如
public E void method(E e){...}
,修飾接口,這裏要注意修飾接口有兩種使用方式:- 第一種:定義接口的實現類,實現接口,指定接口的泛型,比如說
public interface Iterator<E>{
E next();
}
//Scanner實現了Iterator接口,並指定接口的泛型爲String,
//所以重寫的next方法泛型默認是String
public final class Scanner implements Iterator<String>{
public String next(){...}
}
- 第二種:接口使用什麼泛型,實現類就使用什麼泛型,就相當於有定義了一個含有泛型的類,在創建對象時確定泛型的類型
public interface List<E>{
boolean add(E e);
E get(int index);
}
public class ArrayList<E> implements List<E>{
public boolean add(E e){}
public E get(int index){}
}
泛型通配符 ?
? 代表任意的數據類型
注意:
泛型通配符不能創建對象使用ArrayList<?> list = new ArrayList<?>();//這樣是不行的
,只能作爲方法的參數使用
作用:
比如說有幾個不同類型的ArrayList對象,想要有一個方法,能夠把他們都遍歷,此時就可以使用通配符?
public static void main(String[] args){
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
ArrayList<String> list2 = new ArrayList<>();
list1.add("wo");
list1.add("ke");
list1.add("zhen");
list1.add("shi");
list1.add("ge");
list1.add("xian");
list1.add("nv");
list1.add("a");
print(list1);
print(list2);
}
public static void print(ArrayList<?> list){
Iterator<?> it = list.itertor();
while(it.hasNext()){
Object o = it.next();
System.out.println(o);
}
}
泛型總結:
- 泛型是爲了解決某些容器、算法等代碼的通用性而引入,並且能在編譯期間做類型檢查。
- 泛型利用的是 Object 是所有類的祖先類,並且父類的引用可以指向子類對象的特定而工作。
- 泛型是一種編譯期間的機制,即 MyArrayList 和 MyArrayList 在運行期間是一個類型。
- 泛型是Java中的一種合法語法,標誌就是<>
包裝類
Object引用可以指向任意類型的對象,但是8種基本類型並不是對象,那泛型機制如何保證呢?
所以Java種引入了一種特殊的類----包裝類,將8大基本數據類型包裝到對象中,對應關係如下:
基本數據類型 | 對應的包裝類 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
flout | Flout |
double | Double |
char | Character |
boolean | Boolean |
爲了開發方便,Java在編譯期間增加了自動拆箱和自動裝箱機制