目錄
12.1:為什么要有泛型?
12.2:在集合中使用泛型
12.3:自定義泛型結構
12.4:泛型在繼承上的體現(xiàn)
12.5:通配符的使用
12.1:為什么要有泛型?
????????泛型:(標簽)允許在定義類、接口時候通過一個標識來表示類中某個屬性的類型或者是某個方法的返回值及參數(shù)類型。這個類型、參數(shù)將在使用時(例如:繼承或實現(xiàn)這個接口,用這個類型聲明變量、創(chuàng)建對象時)確定(即傳入實際的類型參數(shù),也稱為類型實參)
? ? ? ? JDK 1.5改寫了集合框架中的全部接口和類,為這些接口、類增加了泛型支持,從而可以在聲明集合變量、創(chuàng)建集合對象時傳入類型實參
12.2:在集合中使用泛型
package com.jiayifeng.java;
import org.junit.Test;
import java.util.*;
/**
* author 愛編程的小賈
* create 2023-10-08 19:45
*
* 一:泛型的使用
* 1.jdk 1.5新增的特性
* 2.在集合中使用泛型:
* 總結:
* ①集合接口或集合類在jdk 5.0時都修改為帶泛型的結構
* ②在實例化集合類時,可以指明具體的泛型類型
* ③指明完以后,在集合類或接口中凡是定義類或接口時,內(nèi)部結構使用到類的泛型的位置,都
* 指定為實例化的泛型類型
* 比如:add(E e) ---> 實例化以后:add(Integer e)
* ④注意點:泛型的類型必須是類,不能是基本數(shù)據(jù)類型。需要用到基本數(shù)據(jù)類型的位置,拿包裝類替換
* ⑤如果實例化時,沒有指明泛型的類型。默認類型為java.lang.Object類型
*/
public class GenericTest {
@Test
public void test1(){
// 在集合中使用泛型之前的情況:
ArrayList list = new ArrayList();
// 需求:存放學生的成績
list.add(78);
list.add(43);
list.add(99);
list.add(67);
// 問題一:類型不安全
// list.add("Tom");
for(Object score : list){
// 問題二:強轉時,可能出現(xiàn)ClassCastException
int stuScore = (Integer) score;
System.out.println(stuScore);
}
}
@Test
public void test2(){
// 在集合中使用泛型的情況:以ArrayList為例
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(78);
list.add(67);
list.add(100);
// 編譯時,就會進行類型檢查,保證數(shù)據(jù)的安全
// list.add("Tom");
方式一:
// for(Integer score : list){
避免了強轉操作
// System.out.println(score);
// }
// 方式二:
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
int stuScore = iterator.next();
System.out.println(stuScore);
}
}
@Test
public void test3(){
// 在集合中使用泛型的情況:以HashMap為例
// HashMap<String, Integer> map = new HashMap<String, Integer>();
// jdk 7新特性:類型推斷
HashMap<String, Integer> map = new HashMap();
map.put("Tom",23);
map.put("Jerry",42);
map.put("Jack",17);
map.put("Marry",24);
// 泛型的嵌套
Set<Map.Entry<String,Integer>> entry = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> e = iterator.next();
String key = e.getKey();
Integer value = e.getValue();
System.out.println(key + "---" + value);
}
}
}
12.3:自定義泛型結構
? ? ? ? ①泛型類可能有多個參數(shù),此時應將多個參數(shù)一起放在尖括號內(nèi)。比如:<E1,E2,E3>
? ? ? ? ②實例化后,操作原來泛型位置的結構必須與指定的泛型類型一致
? ? ? ? ③泛型不同的引用不可以相互賦值
? ? ? ? ④如果泛型結構是一個接口或抽象類,則不可以創(chuàng)建泛型類的對象
? ? ? ? ⑤jdk 1.7,泛型的簡化操作:ArrayList<Fruit> flist = new ArrayList<>();
? ? ? ? ⑥泛型的指定中不能使用基本數(shù)據(jù)類型,可以使用包裝類替換
? ? ? ? ⑦在類/接口上聲明的泛型,在本類或本接口中即代表某種類型,可以作為非靜態(tài)屬性的類型、非靜態(tài)方法的參數(shù)類型、非靜態(tài)方法的返回值類型。但在靜態(tài)方法中不能使用類的泛型
? ? ? ? ⑧異常類不能是泛型的
? ? ? ? ⑨父類有泛型,子類可以選擇保留泛型也可以選擇指定泛型類型:
? ? ? ? ? ? ? ? 子類不保留父類的泛型:按需實現(xiàn)
? ? ? ? ? ? ? ? ? ? ? ? 沒有類型 擦除
? ? ? ? ? ? ? ? ? ? ? ? 具體類型
? ? ? ? ? ? ? ? 子類保留父類的泛型:泛型子類
? ? ? ? ? ? ? ? ? ? ? ? 全部保留
? ? ? ? ? ? ? ? ? ? ? ? 部分保留文章來源:http://www.zghlxwxcb.cn/news/detail-727440.html
? ? ? ? 結論:子類必須是“富二代”,子類除了指定或保留父類的泛型,還可以增加自己的泛型文章來源地址http://www.zghlxwxcb.cn/news/detail-727440.html
package com.jiayifeng.java;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* author 愛編程的小賈
* create 2023-10-09 15:11
*
* 一:如何自定義泛型結構:泛型類、泛型接口;泛型方法
* 1.如何定義泛型類 、泛型接口
*/
public class GenericTest1 {
@Test
public void test(){
// 如果定義了泛型類,實例化沒有指明類的泛型,則認為此泛型類型為Object類型
// 要求:如果定義的類是帶泛型的,建議在實例化時要指明類的泛型
Order order = new Order();
order.setOrderT(123);
order.setOrderT("ABC");
// 建議:實例化時指明類的泛型
Order<String> order1 = new Order("orderAA",1001,"orderAA");
order1.setOrderT("AA:hello");
}
@Test
public void test1(){
SubOrder subOrder = new SubOrder();
// 由于子類在繼承帶泛型的父類時指明了泛型類型。則實例化子類對象時,不需要再指明泛型
subOrder.setOrderT(1122);
SubOrder1<String> subOrder1 = new SubOrder1();
subOrder1.setOrderT("Order1...");
}
@Test
public void test2(){
// 泛型不同的引用不能相互賦值
ArrayList<String> list1 = null;
ArrayList<Integer> list2 = null;
// error
// list1 = list2;
}
// 測試泛型方法
@Test
public void test3(){
Order<String> order = new Order<>();
Integer[] arr = new Integer[]{1,2,3,4};
// 泛型方法在調(diào)用時,指明泛型參數(shù)的類型
List<Integer> list = order.copyFromArrayToList(arr);
System.out.println(list);
}
}
package com.jiayifeng.java;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* author 愛編程的小賈
* create 2023-10-09 15:04
*
* 一:自定義泛型類
*/
public class Order<T> {
String orderName;
int orderId;
// 類的內(nèi)部結構就可以使用類的泛型
T orderT;
public Order(){
// 編譯不通過
// T[] arr = new T[10];
// 編譯通過
T[] arr = (T[])new Object[10];
}
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;
}
@Override
public String toString() {
return "Order{" +
"orderName='" + orderName + '\'' +
", orderId=" + orderId +
", orderT=" + orderT +
'}';
}
// 靜態(tài)方法中不可以使用類的泛型
// 靜態(tài)方法早于類的創(chuàng)建
// public static void show(T orderT){
// System.out.println(orderT);
// }
// 泛型方法:在方法中出現(xiàn)了泛型的結構,泛型參數(shù)與類的泛型參數(shù)沒有任何關系
// 換句話說,泛型方法所屬的類是不是泛型類都沒有關系
// 泛型方法,可以聲明為靜態(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;
}
}
package com.jiayifeng.java;
/**
* author 愛編程的小賈
* create 2023-10-09 15:21
*/
public class SubOrder extends Order<Integer>{//SubOrder:不是泛型類
}
package com.jiayifeng.java;
/**
* author 愛編程的小賈
* create 2023-10-09 15:24
*/
public class SubOrder1<T> extends Order<T>{//SubOrder1<T>:仍然是泛型類
}
12.4:泛型在繼承上的體現(xiàn)
12.5:通配符的使用
package com.jiayifeng.java2;
import org.junit.Test;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* author 愛編程的小賈
* create 2023-10-09 16:32
*
* 一:泛型在繼承方面的使用
*
* 二:通配符的使用
*/
public class GenericTest {
/*
1.泛型在繼承方面的使用
雖然類A是類B的父類,但是G<A>和G<B>二者不具備子父類關系,二者是并列關系
補充:類A是類B的父類,A<G>是B<G>的父類
*/
@Test
public void test(){
Object obj = null;
String str = null;
obj = str;
Object[] arr1 = null;
String[] arr2 = null;
arr1 = arr2;
List<Object> list1 = null;
List<String> list2 = new ArrayList<String>();
// 此時的list1和list2的類型不具有子父類關系
// list1 = list2;
/*
反證法:
假設list1 = list2;
list1.add(123);導致混入非String的數(shù)據(jù)。出錯
*/
}
@Test
public void test2(){
AbstractList<String> list1 = null;
List<String> list2 = null;
ArrayList<String> list3 = null;
list1 = list3;
list2 = list3;
}
/*
2.通配符的使用
通配符:?
類A是類B的父類,G<A>和G<B>是沒有關系的,二者共同的父類是:G<?>
*/
@Test
public void test3(){
List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
list = list1;
list = list2;
print(list1);
print(list2);
//
List<String> list3 = new ArrayList<>();
list3.add("AA");
list3.add("BB");
list3.add("CC");
list = list3;
// 添加(寫入):對于List<?>而言,不可以向其內(nèi)部添加數(shù)據(jù)
// 除了添加null之外
// list.add("DD");
list.add(null);
// 獲?。ㄗx?。涸试S讀取數(shù)據(jù),讀取的數(shù)據(jù)類型為Object
Object o = list.get(0);
System.out.println(o);
}
public void print(List<?> list){
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println(obj);
}
}
/*
3.有限制條件的通配符的使用
? extends A:
G<? extends A> 可以作為G<A>和G<B>的父類,其中B是A的子類
? super A
G<? super A> 可以作為G<A>和G<B>的父類,其中B是A的父類
*/
@Test
public void test4(){
List<? extends Person> list1 = null;
List<? super Person> list2 = null;
List<Student> list3 = new ArrayList<Student>();
List<Person> list4 = new ArrayList<Person>();
List<Object> list5 = new ArrayList<Object>();
list1 = list3;
list1 = list4;
// list1 = list5;
// list2 = list3;
list2 = list4;
list2 = list5;
// 讀取數(shù)據(jù)
list1 = list4;
Person p = list1.get(0);
list2 = list4;
Object object = list2.get(0);
// 寫入數(shù)據(jù)
list2.add(new Person());
list2.add(new Student());
}
}
package com.jiayifeng.java2;
/**
* author 愛編程的小賈
* create 2023-10-09 17:17
*/
public class Person {
}
package com.jiayifeng.java2;
/**
* author 愛編程的小賈
* create 2023-10-09 17:17
*/
public class Student extends Person{
}
到了這里,關于第十二章:泛型(Generic)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!