泛型以及萬用字元<?>
阿新 • • 發佈:2020-08-10
泛型(規定集合中存取資料的型別)
泛型的概念
泛型的好處:
建立集合物件,不使用泛型
好處:集合不使用泛型,預設的型別就是object型別,可以儲存任意型別的資料
弊端:不安全,會引發異常
建立集合物件,使用泛型
好處:
1.避免了型別轉換的麻煩,儲存的是什麼型別,取出的就是什麼型別
2.把執行期異常(程式碼執行之後丟擲異常),提升到編譯期(寫程式碼的時候)
弊端:泛型是什麼型別,只能儲存什麼型別的資料
定義和使用含泛型的類
package commonclass; public class TestGeneric01 { public static void main(String[] args) { //不寫泛型,預設泛型為object型別 GenericClass genericClass01 = new GenericClass(); genericClass01.setName("object物件"); Object name = genericClass01.getName();//object型別 System.out.println(name); //在建立物件時,泛型使用Integer型別, GenericClass<Integer> genericClass02 = new GenericClass<>(); genericClass02.setName(1);//自動裝箱 System.out.println(genericClass02.getName());//自動拆箱 //在建立物件時,泛型使用String型別 GenericClass<String> genericClass03 = new GenericClass<>(); genericClass03.setName("張三"); System.out.println(genericClass03.getName()); } } /*定義一個含有泛型的類 * 泛型是一個未知的資料型別,只有在建立物件是才被確定,所有當我們不確定使用什麼資料型別時,可以使用泛型 * 泛型可以接收任何引用資料型別,不能接收基本資料型別(需要用到其包裝類) * 在建立物件的時候,才能確定泛型的資料型別*/ class GenericClass<E> { private E name; public E getName() { return name; } public void setName(E name) { this.name = name; } }
定義和使用含泛型的方法
package commonclass; public class TestGenericMethod01 { public static void main(String[] args) { GenericMethod01 genericMethod01 = new GenericMethod01(); //傳遞什麼型別,泛型就是什麼型別 genericMethod01.printE(1); genericMethod01.printE("hello"); } } /*定義含有泛型的方法:泛型定義在修飾符和返回值之間 * 格式: * 修飾符 <泛型> 返回值 方法名(引數列表(使用泛型)){ * 方法體; * } * 含有泛型的方法,在呼叫方法的時候確定泛型的資料型別 * 傳遞什麼引數,泛型就是什麼型別*/ class GenericMethod01{ public <E> void printE(E e){ System.out.println(e); } }
泛型介面的定義和使用
package commonclass;
//定義含有泛型的介面
public interface GenericIterface<E> {
public abstract void method(E e);
}
package commonclass; //含有泛型的介面的兩種使用方式 //第一種:定義介面的實現類,實現其介面,並指定介面的泛型 public class GenericIterfaceImpl implements GenericIterface<String>{ @Override public void method(String s) { System.out.println(s); } } class Test01{ public static void main(String[] args) { GenericIterfaceImpl genericIterface = new GenericIterfaceImpl(); genericIterface.method("哈哈哈哈"); } }
package commonclass;
//含有泛型的介面的第二種使用方式:介面使用什麼泛型,類就使用什麼泛型,類跟著介面走
//就相當於建立了一個含有泛型的類,建立物件時確定泛型
//注意:類名和介面名後都要加泛型格式
public class GenericIterfaceImpl2<E> implements GenericIterface<E>{
@Override
public void method(E e) {
System.out.println(e);
}
}
class Test2{
public static void main(String[] args) {
GenericIterfaceImpl2<String> genericIterfaceImpl2 = new GenericIterfaceImpl2<>();
genericIterfaceImpl2.method("哈哈哈哈哈哈");
}
}
泛型的萬用字元:<?>
?:代表任意型別的資料
使用方式:不能建立物件時使用,只能作為方法引數使用
package commonclass;
import java.util.ArrayList;
public class TestGeneric02 {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
ArrayList<String> arrayList1 = new ArrayList<>();
arrayList1.add("abc");
arrayList1.add("abc");
arrayList1.add("abc");
printArrayList(arrayList);
printArrayList(arrayList1);
}
/*定義一個方法,能夠列印任意資料型別的arrayList集合
* 由於不知道arrayList集合裡面的資料型別,可以用萬用字元來接收資料
* 注意:泛型沒有繼承關係的*/
public static void printArrayList(ArrayList<?> arrayList){//如果寫成ArrayList<object> ,呼叫方法時會出錯,泛型沒有繼承關係的
for (Object o : arrayList) {
System.out.println(o);
}
}
}
萬用字元的高階使用---受限泛型
package commonclass;
import java.util.ArrayList;
import java.util.Collection;
/*
* 泛型的上限限定:<? extends E> 代表泛型只能使用其子類/本身
* 泛型的下限限定:<? super E> 代表泛型只能使用其父類/本身
* */
public class TestGeneric03 {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<>();
Collection<String> list2 = new ArrayList<>();
Collection<Number> list3 = new ArrayList<>();
Collection<Object> list4 = new ArrayList<>();
getElement1(list1);
getElement1(list2);//報錯
getElement1(list3);
getElement1(list4);//報錯
getElement2(list1);//報錯
getElement2(list2);//報錯
getElement2(list3);
getElement2(list4);
}
/*繼承關係
* Integer extends Number extends Object
* String extends Object*/
//泛型的上限限定:<? extends E> 代表泛型只能使用其子類/本身
public static void getElement1(Collection<? extends Number> collection){}
//泛型的下限限定:<? super E> 代表泛型只能使用其父類/本身
public static void getElement2(Collection<? super Number> collection){}
}
練習:鬥地主綜合案例
分析:
package commonclass;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
//模仿鬥地主發牌
public class PracticeAll {
public static void main(String[] args) {
//準備54張牌
Collection<String> arrayList = new ArrayList<>();
arrayList.add("♠");
arrayList.add("♥");
arrayList.add("♣");
arrayList.add("♦");
Collection<String> arrayList2 = new ArrayList<>();
for (int i = 2; i <= 10; i++) {
arrayList2.add(Integer.toString(i));
}
arrayList2.add("J");
arrayList2.add("Q");
arrayList2.add("K");
arrayList2.add("A");
ArrayList<String> list = new ArrayList<>();//54張牌集合
for (String al2 : arrayList2) {
for (String al1 : arrayList) {
list.add(al1+al2);
}
}
list.add("joker");
list.add("JOKER");
//輸出檢查54張牌
for (String s : list) {
System.out.print(s+"\t");
}
System.out.println();
//將54張牌打亂
Collections.shuffle(list);
//輸出檢查54張牌
for (String s : list) {
System.out.print(s+"\t");
}
System.out.println();
//準備四個集合,容納三個人的牌和底牌
ArrayList<String> a1 = new ArrayList<>();
ArrayList<String> a2 = new ArrayList<>();
ArrayList<String> a3 = new ArrayList<>();
ArrayList<String> bottom = new ArrayList<>();
//依次每人發一張牌,留下最後三張牌,插底
for (int i = 0; i < list.size(); i++) {
if (i >= 51) {
bottom.add(list.get(i));
continue;
}
if (i % 3 == 0){
a1.add(list.get(i));
continue;
}
if (i % 3 == 1){
a2.add(list.get(i));
continue;
}
if (i % 3 == 2){
a3.add(list.get(i));
continue;
}
}
//對每個人手中的牌進行排序,按花色型別(這兒還可以優化,先按牌大小,再按花色排序)
Collections.sort(a1);
Collections.sort(a2);
Collections.sort(a3);
Collections.sort(bottom);
//檢視三個人手中的牌,插底的牌
System.out.println("第一個人手中的牌:");
for (String s : a1) {
System.out.print(s+"\t");
}
System.out.println();
System.out.println("第二個人手中的牌:");
for (String s : a2) {
System.out.print(s+"\t");
}
System.out.println();
System.out.println("第三個人手中的牌:");
for (String s : a3) {
System.out.print(s+"\t");
}
System.out.println();
System.out.println("插底的三張牌:");
for (String s : bottom) {
System.out.print(s+"\t");
}
}
}