真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java泛型的概念

本篇內(nèi)容介紹了“Java泛型的概念”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

我們提供的服務(wù)有:成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、太倉ssl等。為近1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的太倉網(wǎng)站制作公司

一、泛型簡(jiǎn)介

1.泛型的概念

  • 所謂泛型,就是允許在定義類、接口時(shí)通過一個(gè)標(biāo)識(shí)表示類中某個(gè)屬性的類型或者是某個(gè)方法的返 回值及參數(shù)類型。這個(gè)類型參數(shù)將在使用時(shí)(例如,繼承或?qū)崿F(xiàn)這個(gè)接口,用這個(gè)類型聲明變量、 創(chuàng)建對(duì)象時(shí)確定(即傳入實(shí)際的類型參數(shù),也稱為類型實(shí)參)。

  • 從JDK 5.0以后,Java引入了“參數(shù)化類型(Parameterized type)”的概念,允許我們?cè)趧?chuàng)建集合時(shí)再指定集合元素的類型,正如:List,這表明該List只能保存字符串類型的對(duì)象。

  • JDK 5.0改寫了集合框架中的全部接口和類,為這些接口、類增加了泛型支持,從而可以在聲明集合變量、創(chuàng)建集合對(duì)象時(shí)傳入類型實(shí)參。

2.泛型的引入背景

集合容器類在設(shè)計(jì)階段/聲明階段不能確定這個(gè)容器到底實(shí)際存的是什么類型的對(duì)象,所以在JDK1.5之前只能把元素類型設(shè)計(jì)為Object,JDK1.5之后使用泛型來解決。因?yàn)檫@個(gè)時(shí)候除了元素的類型不確定,其他的部分是確定的,例如關(guān)于這個(gè)元素如何保存,如何管理等是確定的,因此此時(shí)把元素的類型設(shè)計(jì)成一個(gè)參數(shù),這個(gè)類型參數(shù)叫做泛型。Collection,List,ArrayList 這個(gè)就是類型參數(shù),即泛型。

3.引入泛型的目的

  1. 解決元素存儲(chǔ)的安全性問題,好比商品、藥品標(biāo)簽,不會(huì)弄錯(cuò)。

  2. 解決獲取數(shù)據(jù)元素時(shí),需要類型強(qiáng)制轉(zhuǎn)換的問題,好比不用每回拿商品、藥品都要辨別。

Java泛型可以保證如果程序在編譯時(shí)沒有發(fā)岀警告,運(yùn)行時(shí)就不會(huì)產(chǎn)生ClassCastException異常。同時(shí),代碼更加簡(jiǎn)潔、健壯。

二、泛型在集合中的應(yīng)用

1. 在集合中沒有使用泛型的例子

@Test
public void test1(){
    ArrayList list = new ArrayList();
    //需求:存放學(xué)生的成績(jī)
    list.add(78);
    list.add(76);
    list.add(89);
    list.add(88);
    //問題一:類型不安全
    //        list.add("Tom");

    for(Object score : list){
        //問題二:強(qiáng)轉(zhuǎn)時(shí),可能出現(xiàn)ClassCastException
        int stuScore = (Integer) score;

        System.out.println(stuScore);

    }

}

圖示:

Java泛型的概念

2. 在集合中使用泛型的例子1

//在集合中使用泛型,以ArrayList為例
@Test
public void test1(){
    ArrayList list = new ArrayList<>();
    list.add("AAA");
    list.add("BBB");
    list.add("FFF");
    list.add("EEE");
    list.add("CCC");
	//遍歷方式一:
    Iterator iterator = list.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
    System.out.println("-------------");
    //便利方式二:
    for (String str:
         list) {
        System.out.println(str);
    }
}

圖示:

Java泛型的概念

3. 在集合中使用泛型例子2

@Test
//在集合中使用泛型的情況:以HashMap為例
public void test2(){
    Map map = new HashMap<>();//jdk7新特性:類型推斷
    map.put("Tom",26);
    map.put("Jarry",30);
    map.put("Bruce",28);
    map.put("Davie",60);
    //嵌套循環(huán)
    Set> entries = map.entrySet();
    Iterator> iterator = entries.iterator();

    while (iterator.hasNext()){
        Map.Entry entry = iterator.next();
        String key = entry.getKey();
        Integer value = entry.getValue();
        System.out.println(key+"="+value);
    }

}

4. 集合中使用泛型總結(jié):

① 集合接口或集合類在JDK 5.0時(shí)都修改為帶泛型的結(jié)構(gòu)。

② 在實(shí)例化集合類時(shí),可以指明具體的泛型類型

③ 指明完以后,在集合類或接口中凡是定義類或接口時(shí),內(nèi)部結(jié)構(gòu)(比如:方法、構(gòu)造器、屬性等)使用到類的泛型的位置,都指定為實(shí)例化的泛型類型。

    比如:add(E e) --->實(shí)例化以后:add(Integer e)

④ 注意點(diǎn):泛型的類型必須是類,不能是基本數(shù)據(jù)類型。需要用到基本數(shù)據(jù)類型的位置,拿包裝類替換

⑤ 如果實(shí)例化時(shí),沒有指明泛型的類型。默認(rèn)類型為java.lang.Object類型。

三、自定義泛型結(jié)構(gòu)

泛型類、泛型接口、泛型方法

1. 泛型的聲明

  • interface List 和 class GenTest其中,T,K,V,不代表值,而是表示類型。這里使用任意字母都可以。

  • 常用T表示,是Type的縮寫。

2. 泛型的實(shí)例化:

一定要在類名后面指定類型參數(shù)的值(類型)。如:

List strList =new ArrayList();

Iterator iterator = customers.iterator();

  • T只能是類,不能用基本數(shù)據(jù)類型填充。但可以使用包裝類填充

  • 把一個(gè)集合中的內(nèi)容限制為一個(gè)特定的數(shù)據(jù)類型,這就是 generics背后的核心思想

//JDK 5.0以前
Comparable c = new Date();
System.out.println(c.comparaTo("red");
                   
//JDK 5.0以后
Comparable  c = new Date();
System.out.println(c.comparaTo("red");

總結(jié):使用泛型的主要優(yōu)點(diǎn)在于能夠在編譯時(shí)而不是在運(yùn)行時(shí)檢測(cè)錯(cuò)誤

3. 注意點(diǎn)

  1. 泛型類可能有多個(gè)參數(shù),此時(shí)應(yīng)將多個(gè)參數(shù)一起放在尖括號(hào)內(nèi)。比如

  2. 泛型類的構(gòu)造器如下: public GenericClass(){}

    而下面是錯(cuò)誤的: public GenericClass{}

  3. 實(shí)例化后,操作原來泛型位置的結(jié)構(gòu)必須與指定的泛型類型一致。

  4. 泛型不同的引用不能相互賦值。

    盡管在編譯時(shí) ArrayList和ArrayList是兩種類型,但是,在運(yùn)行時(shí)只有一個(gè)ArrayList被加載到JVM中。

  5. 泛型如果不指定,將被擦除,泛型對(duì)應(yīng)的類型均按照Object處理,但不等價(jià)于Object。

    建議:泛型要使用一路都用。要不用,一路都不要用。

  6. 如果泛型結(jié)構(gòu)是一個(gè)接口或抽象類,則不可創(chuàng)建泛型類的對(duì)象。

  7. JDK 7.0,泛型的簡(jiǎn)化操作: ArrayListfirst= 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ù)組。
  1. 父類有泛型,子類可以選擇保留泛型也可以選擇指定泛型類型:

-   子類不保留父類的泛型:按需實(shí)現(xiàn)
    -   沒有類型---擦除
    -   具體類型
-   子類保留父類的泛型:泛型子類
    -   全部保留
    -   部分保留
-   結(jié)論:子類必須是“富二代”,子類除了指定或保留父類的泛型,還可以增加自己的泛型

代碼示例:

class Father {
}

/**
 * 定義泛型子類Son
 * 情況一:繼承泛型父類后不保留父類的泛型
 */
//1.沒有指明類型  擦除
class Son1 extends Father {//等價(jià)于class Son1 extends Father{}
}

//2.指定具體類型
class Son2 extends Father {
}

/**
 * 定義泛型子類Son
 * 情況二:繼承泛型父類后保留泛型類型
 */
//1.全部保留
class Son3 extends Father {
}

//2.部分保留
class Son4 extends Father{
}

4. 自定義泛型結(jié)構(gòu)

4.1自定義泛型類

代碼示例:

/**
 * 自定義泛型類Order
 */
class Order {
    private String orderName;
    private int orderId;
    //使用T類型定義變量
    private T orderT;

    public Order() {
    }
    //使用T類型定義構(gòu)造器
    public Order(String orderName, int orderId, T orderT) {
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }

    //這個(gè)不是泛型方法
    public T getOrderT() {
        return orderT;
    }
    //這個(gè)不是泛型方法
    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }
    //這個(gè)不是泛型方法
    @Override
    public String toString() {
        return "Order{" +
                "orderName='" + orderName + '\'' +
                ", orderId=" + orderId +
                ", orderT=" + orderT +
                '}';
    }
//    //靜態(tài)方法中不能使用類的泛型。
//    public static void show(T orderT){
//        System.out.println(orderT);
//    }

//    //try-catch中不能是泛型的。
//    public void show(){
//        try {
//
//        }catch (T t){
//
//        }
//    }

    //泛型方法:在方法中出現(xiàn)了泛型的結(jié)構(gòu),泛型參數(shù)與類的泛型參數(shù)沒有任何關(guān)系。
    //換句話說,泛型方法所屬的類是不是泛型類都沒有關(guān)系。
    //泛型方法,可以聲明為靜態(tài)的。
    // 原因:泛型參數(shù)是在調(diào)用方法時(shí)確定的。并非在實(shí)例化類時(shí)確定。
    public static  List copyFromArryToList(E[] arr) {
        ArrayList list = new ArrayList<>();
        for (E e :
                list) {
            list.add(e);
        }
        return list;
    }
}

自定義泛型類Order的使用

@Test
public void test1() {
    //如果定義了泛型類,實(shí)例化沒有指明類的泛型,則認(rèn)為此泛型類型為Object類型
    //要求:如果大家定義了類是帶泛型的,建議在實(shí)例化時(shí)要指明類的泛型。
    Order order = new Order();
    order.setOrderT(123);
    System.out.println(order.getOrderT());

    order.setOrderT("abc");
    System.out.println(order.getOrderT());

    //建議:實(shí)例化時(shí)指明類的泛型
    Order order1 = new Order<>("Tom", 16, "male");
    order1.setOrderT("AA:BBB");
    System.out.println(order1.getOrderT());
}

@Test
//調(diào)用泛型方法
public void test2(){
    Order order = new Order<>();
    Integer [] arr = new Integer[]{1,2,3,4,5,6};

    List list = order.copyFromArryToList(arr);
    System.out.println(list);
}
4.2自定義泛型接口

代碼示例:

/**
 * 自定義泛型接口
 */
public interface DemoInterface  {
    void show();
    int size();
}

//實(shí)現(xiàn)泛型接口
public class Demo implements DemoInterface {
    @Override
    public void show() {
        System.out.println("hello");
    }

    @Override
    public int size() {
        return 0;
    }
}

@Test
//測(cè)試泛型接口
public void test3(){
    Demo demo = new Demo();
    demo.show();
}
4.3自定義泛型方法
  • 方法,也可以被泛型化,不管此時(shí)定義在其中的類是不是泛型類。在泛型方法中可以定義泛型參數(shù),此時(shí),參數(shù)的類型就是傳入數(shù)據(jù)的類型。

  • 泛型方法的格式: [訪問權(quán)限]<泛型>返回類型 方法名(泛型標(biāo)識(shí) 參數(shù)名稱])拋出的異常

  • 泛型方法聲明泛型時(shí)也可以指定上限

代碼示例:

//泛型方法:在方法中出現(xiàn)了泛型的結(jié)構(gòu),泛型參數(shù)與類的泛型參數(shù)沒有任何關(guān)系。
//換句話說,泛型方法所屬的類是不是泛型類都沒有關(guān)系。
//泛型方法,可以聲明為靜態(tài)的。
// 原因:泛型參數(shù)是在調(diào)用方法時(shí)確定的。并非在實(shí)例化類時(shí)確定。
public static  List copyFromArryToList(E[] arr) {
    ArrayList list = new ArrayList<>();
    for (E e :
         list) {
        list.add(e);
    }
    return list;
}
4.4總結(jié):
  • 泛型實(shí)際上就是標(biāo)簽,聲明時(shí)不知道類型,再使用時(shí)指明

  • 定義泛型結(jié)構(gòu),即:泛型類、接口、方法、構(gòu)造器時(shí)貼上泛型的標(biāo)簽

  • 用泛型定義類或借口是放到類名或接口名后面,定義泛型方法時(shí)在方法名前加上

5.泛型的應(yīng)用場(chǎng)景

【DAO.java】:定義了操作數(shù)據(jù)庫中的表的通用操作。 ORM思想(數(shù)據(jù)庫中的表和Java中的類對(duì)應(yīng))

public class DAO {//表的共性操作的DAO

    //添加一條記錄
    public void add(T t){

    }

    //刪除一條記錄
    public boolean remove(int index){

        return false;
    }

    //修改一條記錄
    public void update(int index,T t){

    }

    //查詢一條記錄
    public T getIndex(int index){

        return null;
    }

    //查詢多條記錄
    public List getForList(int index){

        return null;
    }

    //泛型方法
    //舉例:獲取表中一共有多少條記錄?獲取最大的員工入職時(shí)間?
    public  E getValue(){

        return null;
    }

}

【CustomerDAO.java】:

public class CustomerDAO extends DAO{//只能操作某一個(gè)表的DAO
}

【StudentDAO.java】:

public class StudentDAO extends DAO {//只能操作某一個(gè)表的DAO
}

四、泛型在繼承上的體現(xiàn)

泛型在繼承方面的體現(xiàn):

雖然類A是類B的父類,但是G 和G二者不具備子父類關(guān)系,二者是并列關(guān)系。

補(bǔ)充:類A是類B的父類,A 是 B 的父類

代碼示例:

@Test
public void test1(){

    Object obj = null;
    String str = null;
    obj = str;

    Object[] arr1 = null;
    String[] arr2 = null;
    arr1 = arr2;
    //編譯不通過
    //        Date date = new Date();
    //        str = date;
    List list1 = null;
    List list2 = new ArrayList();
    //此時(shí)的list1和list2的類型不具子父類關(guān)系
    //編譯不通過
    //        list1 = list2;
    /*
        反證法:
        假設(shè)list1 = list2;
           list1.add(123);導(dǎo)致混入非String的數(shù)據(jù)。出錯(cuò)。

         */

    show(list1);
    show1(list2);
}

public void show1(List list){

}

public void show(List list){

}

@Test
public void test2(){

    AbstractList list1 = null;
    List list2 = null;
    ArrayList list3 = null;

    list1 = list3;
    list2 = list3;

    List list4 = new ArrayList<>();

}

五、通配符

1.通配符的使用

  1. 使用類型通配符:?

    比如:List,Map

    List是List、List等各種泛型List的父類。

  2. 讀取List的對(duì)象list中的元素時(shí),永遠(yuǎn)是安全的,因?yàn)椴还躭ist的真實(shí)類型是什么,它包含的都是Object

  3. 寫入list中的元素時(shí),不可以。因?yàn)槲覀儾恢纁的元素類型,我們不能向其中添加對(duì)象。 除了添加null之外。

  4. 說明:

    • 將任意元素加入到其中不是類型安全的

      Collection c = new ArrayList()

      c.add(new Object());//編譯時(shí)錯(cuò)誤

      因?yàn)槲覀儾恢纁的元素類型,我們不能向其中添加對(duì)象。add方法有類型參數(shù)E作為集合的元素類型。我們傳給add的任何參數(shù)都必須是一個(gè)已知類型的子類。因?yàn)槲覀儾恢滥鞘鞘裁搭愋停晕覀儫o法傳任何東西進(jìn)去。

    • 唯一的例外的是null,它是所有類型的成員。

    • 我們可以調(diào)用get()方法并使用其返回值。返回值是一個(gè)未知的類型,但是我們知道,它總是一個(gè)Object。

    代碼示例:

    @Test
    public void test3(){
        List list1 = null;
        List list2 = null;
    
        List list = null;
    
        list = list1;
        list = list2;
        //編譯通過
        //        print(list1);
        //        print(list2);
    
        //
        List list3 = new ArrayList<>();
        list3.add("AA");
        list3.add("BB");
        list3.add("CC");
        list = list3;
        //添加(寫入):對(duì)于List就不能向其內(nèi)部添加數(shù)據(jù)。
        //除了添加null之外。
        //        list.add("DD");
        //        list.add('?');
    
        list.add(null);
    
        //獲取(讀取):允許讀取數(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);
        }
    }

    2.注意點(diǎn)

    //注意點(diǎn)1:編譯錯(cuò)誤:不能用在泛型方法聲明上,返回值類型前面<>不能使用?
    public static  void test(ArrayList list){
        
    }
    
    //注意點(diǎn)2:編譯錯(cuò)誤:不能用在泛型類的聲明上
    class GenericTypeClass{
        
    }
    
    //注意點(diǎn)3:編譯錯(cuò)誤:不能用在創(chuàng)建對(duì)象上,右邊屬于創(chuàng)建集合對(duì)象
    ArrayList<> list2 new ArrayList();

    3.有限制的通配符

    • :允許所有泛型的引用調(diào)用

    • 通配符指定上限

      上限extends:使用時(shí)指定的類型必須是繼承某個(gè)類,或者實(shí)現(xiàn)某個(gè)接口,即<=

    • 通配符指定下限

      下限super:使用時(shí)指定的類型不能小于操作的類,即>=

    • 舉例:

      • (無窮小, Number\] 只允許泛型為Number及Number子類的引用調(diào)用

      • \[Number,無窮大) 只允許泛型為Number及Number父類的引用調(diào)用

      • 只允許泛型為實(shí)現(xiàn) Comparable接口的實(shí)現(xiàn)類的引用調(diào)用

    代碼示例:

    @Test
    public void test4(){
    
        List list1 = null;
        List list2 = null;
    
        List list3 = new ArrayList();
        List list4 = new ArrayList();
        List list5 = new ArrayList();
    
        list1 = list3;
        list1 = list4;
        //        list1 = list5;
    
        //        list2 = list3;
        list2 = list4;
        list2 = list5;
    
        //讀取數(shù)據(jù):
        list1 = list3;
        Person p = list1.get(0);
        //編譯不通過
        //Student s = list1.get(0);
    
        list2 = list4;
        Object obj = list2.get(0);
        ////編譯不通過
        //        Person obj = list2.get(0);
    
        //寫入數(shù)據(jù):
        //編譯不通過
        //        list1.add(new Student());
    
        //編譯通過
        list2.add(new Person());
        list2.add(new Student());
    
    }

    “Java泛型的概念”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!


    名稱欄目:Java泛型的概念
    文章網(wǎng)址:http://weahome.cn/article/gicdcc.html

    在線咨詢

    微信咨詢

    電話咨詢

    028-86922220(工作日)

    18980820575(7×24)

    提交需求

    返回頂部