網(wǎng)站維護會導致打不開網(wǎng)頁嗎?網(wǎng)絡(luò)推廣企劃
泛型機制
本質(zhì)是參數(shù)化類型(與方法的形式參數(shù)比較,方法是參數(shù)化對象)。
優(yōu)勢:將類型檢查由運行期提前到編譯期。減少了很多錯誤。
泛型是jdk5.0的新特性。
集合中使用泛型
總結(jié):
- ① 集合接口或集合類在jdk5.0時都修改為帶泛型的結(jié)構(gòu)
- ② 在實例化集合類時,可以指明具體的泛型類型
- ③ 指明完以后,在集合類或接口中凡是定義類或接口時,內(nèi)部結(jié)構(gòu)(比如:方法、構(gòu)造器、屬性)使用到類的泛型的位置,都指定為實例化的泛型類型。
- 比如:add(E e) ---->實例化以后:add(Integer e)
- ④ 注意點:泛型的類型必須是類,不能是基本數(shù)據(jù)類型。需要用到基本數(shù)據(jù)類型的位置,拿包裝類替換。
- ⑤ 如果實例化時,沒有指明泛型的類型。默認類型為java.lang.Object類型。
public class GenericTest {@Testpublic void test(){//沒有使用泛型機制ArrayList list = new ArrayList();list.add(111);list.add(112);//問題一:類型不安全list.add("tom");for (Object score : list){//問題二:強制轉(zhuǎn)換時,可能會報java.lang.ClassCastExceptionint sc = (int) score;System.out.println(sc);}}@Testpublic void test1(){//使用泛型,以ArrayList為例ArrayList<Integer> list = new ArrayList<Integer>();list.add(122);list.add(44);//編譯時,會進行類型檢查,保證數(shù)據(jù)的安全//list.add("tom");//方式一:for (Integer score:list) {//避免了強制轉(zhuǎn)換操作System.out.println(score);}//方式二:IteratorIterator<Integer> iterator = list.iterator();while (iterator.hasNext()){int score = iterator.next();System.out.println(score);}//使用泛型,以HashMap為例Map<String, Integer> map = new HashMap<>();//jdk7新特性:類型推斷HashMap<String, Integer> map1 = new HashMap<>();map.put("tom",111);map.put("jerry",25);//泛型的嵌套Set<Map.Entry<String, Integer>> entries = map.entrySet();Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator();while (iterator1.hasNext()){Map.Entry<String, Integer> next = iterator1.next();System.out.println(next);}}
}
自定義泛型結(jié)構(gòu)
泛型類
public class Order<T> {String orderName;int orderId;//類的內(nèi)部結(jié)構(gòu)就可以使用類的泛型,可以把它看作是一個類型。T orderT;public Order(){}public Order(String orderName,int orderId,T orderT){this.orderName = orderName;this.orderId = orderId;this.orderT = orderT;}public T getOrderT() {return orderT;}public void setOrderT(T orderT) {this.orderT = orderT;}@Overridepublic String toString() {return "Order{" +"orderName='" + orderName + '\'' +", orderId=" + orderId +", orderT=" + orderT +'}';}
}
測試
public void test(){//如果定義了泛型類,實例化沒有指明類的泛型,則認為此類型為Object類型。//要求:如果大家定義了類時帶泛型的,建議在實例化時要指明類的泛型。Order order = new Order();order.setOrderT(123);order.setOrderT("aaa");//建議實例化時指明類的泛型Order<String> order1 = new Order<String>("aaa",101,"AA");order1.setOrderT("AA:hello");System.out.println(order.toString());}
自定義泛型類、泛型接口注意點補充
1、泛型類可能有多個參數(shù),此時應(yīng)將多個參數(shù)一起放在尖括號內(nèi)。比如:<E1,E2,E3>
2、泛型類的構(gòu)造器如下:public GenericClass(){},而下面的是錯誤的:public GenericClass(){}
3、實例化后,操作原來的泛型位置的結(jié)構(gòu)必須與指定的泛型類型一致。
4、泛型不同的引用不能相互賦值。(盡管在編譯時ArrayList 和 ArrayList 是兩種類型,但是,在運行時只有一個ArrayList被加載到JVM中。)
5、泛型如果不指定,將被擦除,泛型對應(yīng)的類型均按照Object處理,但不等價與Object。經(jīng)驗:泛型要使用一路都用。要不用,一路都不用。
6、如果泛型類是一個接口或抽象類,則不能創(chuàng)建泛型對象。
7、jdk1.7,泛型的簡化操作:ArrayList flist = new ArrayList<>();
8、泛型的指定中不能使用基本數(shù)據(jù)類型,可以使用包裝類替換。
9、在類/接口上聲明的泛型,在本類或本接口中即代表某種類型,可以作為非靜態(tài)屬性的類型、非靜態(tài)方法的參數(shù)類型、非靜態(tài)方法的返回值類型。但在靜態(tài)方法中不能使用類的泛型。
10、異常類不能是泛型的。
11、不能使用new E[]。但是可以:E[] elements = (E[]) new Object[capacity];參考:ArrayList源碼中聲明:Object[] elementData,而非泛型參數(shù)類型數(shù)組。
12、父類有泛型,子類可以選擇保留泛型也可以選擇指定泛型類型:
- 子類不保留父類的泛型:按需實現(xiàn)
沒有類型 擦除
具體類型 - 子類保留父類的泛型:泛型子類
全部保留
部分保留 - 結(jié)論:子類必須是“富二代”,子類出了指定或保留父類的泛型,還可以增加自已的泛型
靜態(tài)方法中不能使用泛型說明
//靜態(tài)方法中不能使用泛型
// public static void show(T orderT){
// System.out.println(orderT);
//
在程序運行時,首先加載靜態(tài)變量和靜態(tài)方法,而參數(shù)T orderT的泛型定義時在加載靜態(tài)變量和方法之后的
泛型方法
//泛型方法:在方法中出現(xiàn)了泛型結(jié)構(gòu),泛型方法與類的泛型參數(shù)沒有任何關(guān)系。//換句話說,泛型方法所屬類是不是泛型類沒有任何關(guān)系。//泛型方法,可以聲明為靜態(tài)的。原因:泛型參數(shù)時在調(diào)用方法時確定的,并不是在實例化類時確定。public static <E> List<E> copyFromArrayToList(E[] arr){ArrayList<E> list = new ArrayList<>();for(E e: arr){list.add(e);}return list;}
泛型在繼承方面的體現(xiàn)
類A是類B的父類,G<A> 和 G<B>不具備子父類,關(guān)系,是并列關(guān)系。
public void test1(){Object obj = null;String str = null;obj = str;List<Object> list1 = null;List<String> list2 = null;//此時的List1和List2類型不具有子父類關(guān)系。//編譯不通過
// list1 = list2;}
擴展:類A是類B的父類,A<G>是B<G>的父類。
public void test2(){List<String> list1 = null;ArrayList<String> list2 = null;list1 = list2;}
通配符的使用
類A是類B的父類,G<A> 和 G<B>是沒有關(guān)系的,二者的共同父類是:G<?>
public class Test1 {@Testpublic void test1(){List<Object> list1 = null;List<String> list2 = null;List<?> list = null;list = list1;list = list2;print(list1);print(list2);}public void print(List<?> list){Iterator<?> iterator = list.iterator();while (iterator.hasNext()){Object obj = iterator.next();System.out.println(obj);}}
}
使用通配符后讀取寫入的要求
List<?> list = null;
List<String> list3 = new ArrayList<>();list3.add("aa");list3.add("bb");list = list3;//添加(寫入):對于List<?>就不能向其內(nèi)部添加數(shù)據(jù)。//出了添加NULL之外。//List.add("DD");編譯器異常list.add(null);//獲取(讀取):允許讀取數(shù)據(jù),讀取的數(shù)據(jù)類型為ObjectObject o = list.get(0);
有限制條件的通配符使用
通配符指定上限:extends,使用時指定的類型必須是繼承某個類,或者實現(xiàn)某個接口,即<= 。
<? extends Number> (無窮小,Number]:只允許泛型為Number即Number子類的引用調(diào)用。 <? super Number> [Number,無窮大):只允許泛型為Number即Number父類的引用調(diào)用。 <? extends Comparable>:只允許泛型為實現(xiàn)Comparable接口的實現(xiàn)類的引用調(diào)用。
通配符指定下限:super,使用時指定的類型不能小于操作的類,即>= 。
舉例:
測試
創(chuàng)建了兩個類,Student,Person,Person是Student的父類
/*? extends Person:G<? extends Person>可以作為G<A>和G<B>的父類,其中B是A的子類。? super Person:G<? super Person>可以作為G<A>和G<B>的父類,其中B是A的父類。*/
public void test2(){List<? extends Person> list1 = null;List<? super Person> list2 = null;List<Student> list3 = null;List<Person> list4 = null;List<Object> list5 = null;list1 = list3;list1 = list4;//list1 = list5;編譯期異常//list2 = list3;編譯期異常list2 = list4;list2 = list5;//讀取數(shù)據(jù)list1 = list4;Person person = list1.get(0);//編譯不通過//Student s = list1.get(0);list2 = list4;Object obj = list2.get(0);//編譯不通過//Person p = list2.get(0);//寫入數(shù)據(jù)//list1.add(new Student());編譯不通過,list1 ?可能是比Student還要小的類,故不能添加。//編譯通過list2.add(new Person());list2.add(new Student());}