激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - Java泛型定義與用法實例詳解

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

2021-05-28 13:06喜歡特別冷的冬天下著雪 Java教程

這篇文章主要介紹了Java泛型定義與用法,結合實例形式較為詳細的分析了Java中泛型的概念、原理、定義、使用方法及相關操作注意事項,需要的朋友可以參考下

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

1. 泛型的由來

 

先看如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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集合元素的類型,那么就可避免上述不規范操作。代碼如下,

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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. 泛型類型的繼承關系

 

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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 類型通配符

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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 泛型方法

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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 泛型方法和通配符的區別

看如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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 泛型參數上、下限的注意

看如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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:

改為

?
1
number lastelement=new testgeneric().copy(des,src);

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

?
1
2
father f=new child();
child c=f;//此處一定報錯,類型不兼容

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

方法2:

改為

?
1
public <t> t copy(collection<? super t> des,collection<t> src)

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

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

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

原文鏈接:https://blog.csdn.net/kkkkkxiaofei/article/details/18262049

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 精品国产91久久久久 | 久久网站热最新地址 | 爱视频福利 | 97se亚洲综合在线韩国专区福利 | 在线播放亚洲精品 | 在线亚洲播放 | 成人短视频在线播放 | 狠狠久久 | 色婷婷久久一区二区 | 最新中文字幕第一页视频 | 久久久久夜色精品国产老牛91 | 中文字幕在线不卡视频 | 欧美1—12sexvideos| 久久精品久久久久 | 91精品久久久久久久久网影视 | 国产高潮失禁喷水爽到抽搐视频 | 成人福利在线视频 | 在线视频1区 | 91精品国产综合久久婷婷香 | 夜夜夜影院 | 精品久久久久久久久久久久包黑料 | 成人在线免费小视频 | 毛片午夜 | 国产一区二区在线观看视频 | 久久人人爽爽爽人久久久 | 精品久久久久久综合日本 | 色视频91 | 91久久国产综合久久91猫猫 | av在线免费看网站 | 日本一区二区三区高清不卡 | 久久情爱网| 夜夜夜操操操 | 91网站在线播放 | 99精美视频 | 久久综合久久综合久久综合 | 天堂成人一区二区三区 | 日本在线一区二区 | 国产精品自拍av | 国产a级网站 | 夜间福利网站 | 中文字幕在线免费 |