Java學習筆記123——集合—泛型
阿新 • • 發佈:2021-12-22
泛型
泛型的定義及優點
import java.util.ArrayList; import java.util.Iterator; /* ClassCastException:型別轉換異常 我們按照正常的寫法,在集合中新增一些不是同類型的資料,在遍歷的時候向下轉型 報錯了。 為什麼呢? 因為我們在儲存資料的時候,儲存了一些String和Integer型別的資料 但是呢,我們遍歷的時候,預設集合中只存放String型別的資料,但是呢,又沒有在 儲存資料的時候告訴我只能存String型別的資料,突然覺得這樣的設計很不好 如果能在儲存的時候告訴我能儲存哪些資料型別就好了。 就像陣列這樣: String[] arr = new String[3]; arr[0] = "hello"; //arr[1] = 20;--不能儲存 java中集合就模仿著陣列,也有了這樣的做法,在建立集合的時候,就明確了 元素的資料型別,建立後,再往集合中加入的元素的時候,只能是定義好的資料型別相關的 資料了,然後再向下轉型就沒有問題了。 這樣的技術,java中叫做:泛型 泛型: 把明確資料型別的工作,提前到了編譯時期,在建立集合的時候明確資料型別。 這樣的做法有點像把資料型別當作引數一樣進行傳遞。所以泛型還有一個名字 叫做:引數化型別。 定義格式: <引用資料型別> 注意:尖括號中的資料型別只能是引用資料型別 泛型的好處: 1、將我們之前執行時候出現的問題,提前到了編譯時期 2、不需要強制型別轉換了 3、優化了程式碼,消除不必要的黃色警告線 通過觀察API發現,泛型可以出現了類,介面,方法上,看到一些類似與<E>,一般來說泛型 出現在大多使用集合中。 */ public class GenericDemo1 { public static void main(String[] args) { //建立List集合物件 //報錯之後,在建立集合的時候加入泛型,明確集合的資料型別 //賦值號右邊的尖括號裡可以不寫,因為JDK1.7之後會自動進行型別推斷 ArrayList<String> list = new ArrayList<String>(); list.add("hello"); //新增泛型之後就不能存放Integer型別了 //list.add(10); //向上轉型 10 --> int --> Integer list.add("world"); list.add("java"); list.add("bigdata"); //獲取迭代器物件--也要加泛型 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { //加入泛型之後就不需要進行強轉了,因為型別已經明確下來了 String next = iterator.next(); System.out.println(next + "--" + next.length()); //加入泛型之前: // Object next = iterator.next(); //ClassCastException:型別轉換異常 // String s = (String)next; // System.out.println(s); } } }
泛型應用
-
泛型類
/* 泛型類: 把泛型定義在類上 格式:public class 類名<泛型型別1,…> 注意:泛型型別必須是引用型別 這裡的<>裡面的內容僅僅表示的是一種引數資料型別,引數型別是一種變數, 既然是一種變數,就符合變數的命名規則,可以是任意符合識別符號起名規則的名字。 */ public class GenericTool1<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } } import com.shujia.wyh.day22.Student; /* 泛型類的測試 */ public class GenericTest1 { public static void main(String[] args) { //不加泛型不會報錯,預設是Object型別 // GenericTool1 gt1 = new GenericTool1(); //預設是Object型別的時候,我傳入什麼型別的值都可以 // gt1.setObj("hello"); // gt1.setObj(20); // gt1.setObj(12.34); // gt1.setObj(new Student()); //加了泛型之後: GenericTool1<String> gt2 = new GenericTool1<>(); gt2.setObj("hello"); //加了泛型並明確了型別為String型別的時候 //傳入String型別之外的型別就會報錯 // gt2.setObj(20); //明確了String型別之後,返回值就是String型別 String obj = gt2.getObj(); } }
-
泛型方法
/* 泛型方法 把泛型定義在方法上 格式:public <泛型型別> 返回型別 方法名(泛型型別 .) */ public class GenericTool2 <T>{//-第一種方式:在類中指定泛型 //沒有加入泛型的時候 // public void show(String s){ // System.out.println(s); // } // // public void show(int i){ // System.out.println(i); // } // // public void show(double d){ // System.out.println(d); // } //第一種方式:在類中指定泛型,在引數列表裡面使用泛型 // public void show(T t){ // System.out.println(t); // } //第二種方式:不在類中指定泛型 //而是在方法中指定泛型 public <T> void show(T t){ System.out.println(t); } } import com.shujia.wyh.day22.Student; /* 泛型方法的使用 */ public class GenericTest2 { public static void main(String[] args) { //沒有加入泛型的時候每次想要傳入一個新的資料型別 //都要過載一遍show()方法 // GenericTool2 gt1 = new GenericTool2(); // gt1.show(10); // gt1.show("hello"); // gt1.show(12.34); //----------用泛型方法第一種方式改進之後-------- // gt1.show(new Student()); //建立泛型類物件--此時show()方法中只能傳入在初始化泛型類時被宣告的資料型別 // GenericTool2<String> gt2 = new GenericTool2<>(); // gt2.show("hello"); //不能傳入int型別 // //gt2.show(20); //那想要傳入Integer型別怎麼辦呢?只能再建立一個泛型類的物件 // GenericTool2<Integer> gt3 = new GenericTool2<>(); // gt3.show(20); // //到目前為止,如果你能看懂,說明泛型類你是可以掌握的 //但是有個問題,誰規定了方法的引數型別一定要和類的型別一致呢? //如果類上面沒有泛型的話,方法還能不能隨便傳參呢?--可以 //--------用泛型方法第二種方式改進之後-------- //建立物件 GenericTool2 gt = new GenericTool2(); //可以放入任何一種資料型別 gt.show("hello"); gt.show(20); gt.show(true); } }
-
泛型介面
/*
泛型介面
*/
public interface GenericTool3<T> {
public abstract void show(T t);
}
//將來開發中實現介面的類名字後面加上Impl,易於區分
//實現泛型介面的類的類名後面也要加上<T>
public class GenericTool3Impl<T> implements GenericTool3<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
/*
泛型介面的測試
*/
public class GenericTest3 {
public static void main(String[] args) {
//建立實現介面的類的物件
GenericTool3Impl<String> sgt1 = new GenericTool3Impl<>();
sgt1.show("hello");
}
}
泛型高階(萬用字元)
public class Animal {
}
public class Dog extends Animal {
}
public class Cat extends Animal {
}
import java.util.ArrayList;
/*
泛型萬用字元<?>
任意型別,如果沒有明確,那麼就是Object以及任意的Java類了
? extends E
向下限定,E及其子類
? super E
向上限定,E及其父類
*/
public class GenericDemo2 {
public static void main(String[] args) {
//如果泛型裡面的型別只用一個,並且明確資料型別的時候,前後必須要寫一致
ArrayList<Animal> list1 = new ArrayList<Animal>();
ArrayList<Dog> list2 = new ArrayList<Dog>();
ArrayList<Object> list3 = new ArrayList<Object>();
//泛型萬用字元<?>
//任意型別,如果沒有明確,那麼就是Object以及任意的Java類了
ArrayList<?> objects1 = new ArrayList<Animal>();
ArrayList<?> objects2 = new ArrayList<Dog>();
ArrayList<?> objects3 = new ArrayList<Object>();
// ? extends E 向下限定,E及其子類
ArrayList<? extends Animal> list4 = new ArrayList<Animal>();
ArrayList<? extends Animal> list5 = new ArrayList<Dog>();
ArrayList<? extends Animal> list6 = new ArrayList<Cat>();
//向下限定,只能傳入E及其子類,不能是E的父類
//ArrayList<? extends Animal> list7 = new ArrayList<Object>();
// ? super E 向上限定,E及其父類
ArrayList<? super Animal> list7 = new ArrayList<Animal>();
ArrayList<? super Animal> list8 = new ArrayList<Object>();
//向上限定,只能傳入E及其父類,不能是E的子類
//ArrayList<? super Animal> list9 = new ArrayList<Dog>();
}
}