大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學(xué)習(xí)攻略 Java泛型定義與java用法泛型實例詳解

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

更新時間:2019-08-31 09:00:00 來源:動力節(jié)點 瀏覽3032次

  


今天動力節(jié)點java學(xué)院小編為大家介紹“Java泛型定義與java用法泛型實例詳解”,此文結(jié)合實例形式較為詳細的分析了Java中泛型的概念、原理、定義、使用方法及相關(guān)操作注意事項,希望通過此文能夠幫助到那些有需要的小伙伴們,下面各位小伙伴們就隨小編一起看看Java泛型定義與java用法泛型實例詳解吧。



  1、java泛型的由來


  先看如下代碼:


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);

    }

}


運行結(jié)果:


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

1 1 java.lang.Object@1db9742


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


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);// 無需轉(zhuǎn)換

    }

}


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



  2、泛型類型的繼承關(guān)系


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


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>) 應(yīng)用于 (java.util.List<java.lang.String>)

   new TestGeneric().print(list);

                    ^

1 錯誤


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


(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);

    }

}


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


  (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類型是來自哪里。既然泛型方法和類型通配符都可以實現(xiàn)泛型中的繼承,那么有什么區(qū)別?


(3)泛型方法和通配符的區(qū)別


看如下代碼:


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時已經(jīng)指明了關(guān)系:T是E的子類,所以在傳遞參數(shù)的時候,T要么是E的子類,要么就是E本身,所以在傳遞關(guān)系不小心變?yōu)镋 exends T時,在第三次調(diào)用方法時報錯了。而如果把上述代碼換成?通配符的話,則不具有如此強的限定關(guān)系。


  總之,泛型方法和?通配符都可以實現(xiàn)未知類型的繼承,但是泛型方法主要強調(diào)多個未知類型之間的依賴關(guān)系。如果只是單純用作成為一個通用類型的父類這一功能的話,兩者都可以實現(xiàn)。


  (4)泛型參數(shù)上、下限的注意


看如下代碼:


import java.util.List;

import java.util.ArrayList;

import java.util.Collection;

public class TestGeneric {

    // 復(fù)制集合并返回原始集合的最后一個元素

    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 錯誤


當調(diào)用完copy方法后,系統(tǒng)比對發(fā)現(xiàn)T類型為Number,?類型為Integer。所以函數(shù)返回的T類型是Number了,所以根本不兼容Integer。要修改上面的代碼,有2個辦法,


方法1:


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


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


Father f=new Child();

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


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


方法2:


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


這樣一來,?類型變?yōu)榱烁割悾琓類型變?yōu)榱俗宇悾谑窃诜椒ㄖ蟹祷氐腡類型對象,即lastElement就不具有多態(tài)性了。泛型中的上下限是很有學(xué)問的,每次看源碼時都會琢磨很久,但還是會在浩瀚的接口+泛型的設(shè)計中昏迷,這種設(shè)計真的完全是為了突出面向?qū)ο蟮奶匦浴?/p>


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


以上就是動力節(jié)點java學(xué)院小編介紹的“Java泛型定義與java用法泛型實例詳解”的內(nèi)容,希望通過此文能夠幫助到大家,更多精彩內(nèi)容請繼續(xù)關(guān)注動力節(jié)點java學(xué)院官網(wǎng)。



提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)

免費課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 亚洲综合伊人色一区 | 欧美日韩中文在线 | 国产激情久久久久影院小草 | 水中色av综合 | 中文线码中文高清播放中 | 日日撸夜夜撸网站 | 狠狠操天天操视频 | 亚洲二三区 | 亚洲韩国日本一级二级r级 亚洲韩精品欧美一区二区三区 | 欧美国产在线观看 | 久久亚洲一区二区 | 亚洲精品国产第一区二区三区 | 国产男女xoxo在线视频 | 天天艹天天操 | 深夜福利免费观看 | 精品xxxxxbbbb欧美中文 | 日韩欧美亚洲综合久久影院d3 | 女人国产香蕉久久精品 | 亚洲第一a | 国产亚洲高清在线精品99 | 欧美大香a蕉免费 | 91久久福利国产成人精品 | 色片在线| 国内精品久久久久久久亚洲 | 黄色成人免费观看 | 亚洲国产成人久久综合一 | 亚洲日本久久一区二区va | 欧美日本一本线在线观看 | 国产精品久久久久这里只有精品 | 亚洲国产一区二区三区在线观看 | 奇米精品 | 中国特级黄一级真人毛片 | 6一10周岁毛片免费 6一10周岁毛片在线 | 国产精品视频第一区二区三区 | 久久精品国产精品亚洲婷婷 | 激情五月婷婷网 | 免费性视频 | 狠狠色狠狠色很很综合很久久 | 中文字幕在线视频免费 | 久久久久久久国产 | 在线观看理论片 |