91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java泛型定義與用法實例詳解

發布時間:2020-10-21 18:26:14 來源:腳本之家 閱讀:164 作者:喜歡特別冷的冬天下著雪 欄目:編程語言

本文實例講述了Java泛型定義與用法。分享給大家供大家參考,具體如下:

1. 泛型的由來

先看如下代碼:

import java.util.List;
import java.util.ArrayList;
public class TestGeneric {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(1);
        list.add("1");
        list.add(new Object());
        System.out.println(list);
        // 取值
        Integer var1 = (Integer) list.get(0);
        String var2 = (String) list.get(1);
        Object var3 = list.get(2);
        System.out.println(var1 + " " + var2 + " " + var3);
    }
}

運行結果:

[1, 1, java.lang.Object@1db9742]
1 1 java.lang.Object@1db9742

這段代碼很簡單,將整形、字符串、對象放進list集合中,然后逐一取出。可以看出,由于List接口在定義時并不知道元素的類型,因此默認為Object,即任意類型元素進入list集合后都會自動裝箱。而取值的過程更為復雜,所有取得的值都是裝箱后的Object對象,必須得知道每一個元素的初始類型才能拆箱。一般使用集合的時候,集合的元素往往都是具有共同特征的,比如同屬于一類的----那么,如果一開始限定了list集合元素的類型,那么就可避免上述不規范操作。代碼如下,

import java.util.List;
import java.util.ArrayList;
public class TestGeneric {
    @SuppressWarnings("unused")
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        // list.add(1);//報錯
        // list.add(new Object());//報錯
        list.add("1");
        // 取值
        String var1 = list.get(0);// 無需轉換
    }
}

如此一來,便有了泛型集合的說法。實際上,查閱List接口的Api會發現,List接口正是泛型接口,它可以接受一個類型參數E,若不傳遞參數,則默認是Object類型。

2. 泛型類型的繼承關系

有如下功能的代碼,實現打印任意集合的元素:

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
public class TestGeneric{
    //打印任意集合元素
    public void print(Collection<Object> c){
     System.out.println(c);
    }
    public static void main(String[] args){
     List<String> list=new ArrayList<String>();
     new TestGeneric().print(list);
 }
}

輸出:

TestGeneric.java:11: 無法將 TestGeneric 中的 print(java.util.Collection<java.lang.Object>) 應用于 (java.util.List<java.lang.String>)
   new TestGeneric().print(list);
                    ^
1 錯誤

很明顯,意思就是傳遞的參數類型不匹配。難道String不是繼承自Object的嗎?沒錯,String是繼承自Object的,但是List<String>List<Object>是截然不同的兩個類型,兩者之間沒有任何繼承關系。那如果真的要實現上面的功能,該如何呢?

2.1 類型通配符

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
public class TestGeneric {
    // 打印任意集合元素
    public void print(Collection<?> c) {
        System.out.println(c);
    }
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        new TestGeneric().print(list);
    }
}

程序正常執行,這里的?表示一個未知類型,這個未知類型與Object不同,List<?>代表了所有的List<類型>的父類。

2.2 泛型方法

不只有通配符可以解決泛型繼承的問題,若將上面的方法定義為泛型方法也具有同樣的效果:

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
public class TestGeneric {
    // 打印任意集合元素
    public <T> void print(Collection<T> c) {
        System.out.println(c);
    }
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        new TestGeneric().print(list);
    }
}

泛型方法的定義形式如下,

修飾符 <T,E> 返回值 方法名(形參)

其中<T,E>在修飾符的后面做為類型定義,為方法指明形參中需要用到的T,E類型是來自哪里。既然泛型方法和類型通配符都可以實現泛型中的繼承,那么有什么區別?

2.3 泛型方法和通配符的區別

看如下代碼:

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
public class TestGeneric {
    // 打印任意集合元素
    public <E, T extends E> void print(Collection<T> c1, Collection<E> c2) {
        System.out.println(c1);
        System.out.println(c2);
    }
    public static void main(String[] args) {
        List<Father> list1 = new ArrayList<Father>();
        List<Father> list2 = new ArrayList<Father>();
        new TestGeneric().print(list1, list2);// 傳2個father類型
        List<Child> list3 = new ArrayList<Child>();
        List<Father> list4 = new ArrayList<Father>();
        new TestGeneric().print(list3, list4);// T為child,E為father
        List<Father> list5 = new ArrayList<Father>();
        List<Child> list6 = new ArrayList<Child>();
        new TestGeneric().print(list5, list6);// T為father,E為child,報錯
    }
}
class Father {
}
class Child extends Father {
}
class Other {
}

上述泛型方法在定義T,E時已經指明了關系:T是E的子類,所以在傳遞參數的時候,T要么是E的子類,要么就是E本身,所以在傳遞關系不小心變為E exends T時,在第三次調用方法時報錯了。而如果把上述代碼換成?通配符的話,則不具有如此強的限定關系。

總之,泛型方法和?通配符都可以實現未知類型的繼承,但是泛型方法主要強調多個未知類型之間的依賴關系。如果只是單純用作成為一個通用類型的父類這一功能的話,兩者都可以實現,反而?通配符較為簡潔明了。

2.4 泛型參數上、下限的注意

看如下代碼:

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
public class TestGeneric {
    // 復制集合并返回原始集合的最后一個元素
    public <T> T copy(Collection<T> des, Collection<? extends T> src) {
        T lastElement = null;
        for (T t : src) {
            lastElement = t;
            des.add(t);
        }
        return lastElement;
    }
    public static void main(String[] args) {
        List<Number> des = new ArrayList<Number>();
        List<Integer> src = new ArrayList<Integer>();
        src.add(new Integer(1));
        Integer lastElement = new TestGeneric().copy(des, src);//
        System.out.println(lastElement.getClass());
    }
}

輸出:

TestGeneric.java:18: 不兼容的類型
找到: java.lang.Number
需要: java.lang.Integer
Integer lastElement= new TestGeneric().copy(des,src);//
                                              ^
1 錯誤

當調用完copy方法后,系統比對發現T類型為Number,?類型為Integer。所以函數返回的T類型是Number了,所以根本不兼容Integer。要修改上面的代碼,有倆個辦法,

方法1:

改為

Number lastElement=new TestGeneric().copy(des,src);

分析代碼可以得出,?為T的子類,在方法中T=lastElement這句表現為多態,雖然返回的是T類型,但是多態的表現為?類型,即Interger類型,調用lastElement.getClass()也可發現返回的是java.lang.Integer類型,說明此處編譯類型為T類型,實際運行類型為?類型。這就好比如下多態轉換,

Father f=new Child();
Child c=f;//此處一定報錯,類型不兼容

雖然f的多態表現為子類Child,但是上面一句連語法檢測都過不了。這也就是為什么上面Integer不能兼容Number的原因了。

方法2:

改為

public <T> T copy(Collection<? super T> des,Collection<T> src)

這樣一來,?類型變為了父類,T類型變為了子類,于是在方法中返回的T類型對象,即lastElement就不具有多態性了。泛型中的上下限是很有學問的,每次看源碼時都會琢磨很久,但還是會在浩瀚的接口+泛型的設計中昏迷,這種設計真的完全是為了突出面向對象的特性,以后慢慢琢磨吧。

從這也再次可以看出?通配符在處理具有依賴關系的泛型方法中,顯得過于靈活而會導致一些潛在的隱患。

更多關于java算法相關內容感興趣的讀者可查看本站專題:《Java數據結構與算法教程》、《Java操作DOM節點技巧總結》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》

希望本文所述對大家java程序設計有所幫助。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

巨鹿县| 蒙山县| 本溪市| 镇远县| 印江| 道真| 兴仁县| 武功县| 诏安县| 迁安市| 博白县| 镶黄旗| 铜川市| 大同县| 县级市| 安阳市| 仲巴县| 新建县| 平江县| 定结县| 外汇| 农安县| 三门峡市| 原平市| 会昌县| 长垣县| 平武县| 兴宁市| 内黄县| 罗山县| 丰都县| 遂宁市| 玉环县| 新竹市| 河东区| 息烽县| 什邡市| 连云港市| 海兴县| 贡觉县| 蒙阴县|