Java泛型詳解(一)

1、什么是泛型

泛型,是“參數(shù)化類型”的概念,代碼可以適用于多種類型。參數(shù)化類型是指把具體的類型參數(shù)化,就像方法中使用的參數(shù)一樣。

    void hello(String str){
        System.out.println("str是個(gè)變量參數(shù),String是個(gè)具體類型");
    }
    <T> void hello(T str){
        System.out.println("str是個(gè)變量參數(shù),T是個(gè)類型參數(shù)");
    }

2、為什么使用泛型

泛型出現(xiàn)最引人注目的一個(gè)原因,是為了創(chuàng)造使用容器類。
        List arrayList=new ArrayList();
        arrayList.add("hello");
        arrayList.add(110);
        for(Object obj:arrayList){
            String s=(String)obj;//java.lang.ClassCastException
        }

有些情況下,我們希望容器能夠持有多種類型的對(duì)象,但是,大部分情況我們只會(huì)使用容器存儲(chǔ)一種類型的對(duì)象,泛型可以在編譯階段就可以防止錯(cuò)誤的發(fā)生。

List<String> arrayList=new ArrayList<String>();
arrayList.add(110);//編譯時(shí)報(bào)錯(cuò)
另外,一般的類和方法,只能使用具體的類型。如果要編寫可以應(yīng)用于多種類型的代碼,這種刻板的限制就會(huì)對(duì)代碼造成束縛。

return語(yǔ)句只能返回一個(gè)對(duì)象,但是有很多功能要求一個(gè)方法需要返回多個(gè)對(duì)象,怎么辦?
解決方法就是創(chuàng)建一個(gè)對(duì)象,用它來(lái)持有返回的多個(gè)對(duì)象??梢栽诿看问剐枰獣r(shí),專門創(chuàng)建一個(gè)類,而使用泛型則能夠一次性解決該問(wèn)題,同時(shí)在編譯期間就能確保類型安全。

public class TwoTuple <A,B>{
    public final A a;
    public final B b;
    public TwoTuple(A a,B b) {
        this.a=a;
        this.b=b;
    }
}

例:獲取一個(gè)學(xué)生的信息和導(dǎo)師的姓名。

public class TupleTest{
    public static void main(String[] args) {
        TwoTuple<Student,String> tt=new TwoTuple<Student, String>(new Student(), "張大俠");
    }
}
class Student{}

3、泛型特性

泛型只在編譯階段有效

        List<String> stringArrayList = new ArrayList<String>();
        List<Integer> integerArrayList = new ArrayList<Integer>();
        Class<? extends List> classStringArrayList = stringArrayList.getClass();
        Class<? extends List> classIntegerArrayList = integerArrayList.getClass();
        if(classStringArrayList.equals(classIntegerArrayList)){
            System.out.println("類型相同");
        }

輸出:

類型相同

泛型不強(qiáng)制使用,泛型也無(wú)法顯示用于運(yùn)行時(shí)類型的操作,例如轉(zhuǎn)型、instanceof和new表達(dá)式。

    public void testClass(){
        GenricClass<Integer> gci=new GenricClass<Integer>(10086);
//      GenricClass<String> gcs=new GenricClass<String>(10086);
        GenricClass<String> gcs=new GenricClass<String>("hello");
        GenricClass g1=new GenricClass(10086);
        GenricClass g2=new GenricClass("hello");
        GenricClass g3=new GenricClass(66.666);
        GenricClass g4=new GenricClass(true);
        System.out.println(g1.getField());
        System.out.println(g2.getField());
        System.out.println(g3.getField());
        System.out.println(g4.getField());
        if(g2 instanceof GenricClass<?>){//if(g2 instanceof GenricClass<String>) 編譯錯(cuò)誤
            System.out.println("true");
        }
    }

Java泛型是使用擦除來(lái)實(shí)現(xiàn)的,意思是當(dāng)你使用泛型的時(shí)候,任何具體的類型信息都被擦除了,你唯一知道的就是你在使用一個(gè)對(duì)象。List<String> 和List<Integer>在運(yùn)行時(shí)是相同的類型,都被擦除成他們的原生類型,即List。
擦除默認(rèn)會(huì)把類型擦除到Object,如果需要使用具體類的某些特性,需要協(xié)助泛型類,給泛型類定個(gè)邊界。

    class Shape{int length() {return 0;}}
    class Rectangle extends Shape{}
    class Circle extends Shape{}
    class Painter<T extends Shape>{
        private T t;
        public Painter(T t) {this.t=t;}
        public void draw(){
            t.length();
        }
    }

在上面這個(gè)例子中,泛型并沒(méi)有貢獻(xiàn)什么好處,只要把T替換成Shape就可以很容易創(chuàng)建出沒(méi)有泛型的類,這也說(shuō)明一點(diǎn):只有當(dāng)你是用的類型參數(shù)比某個(gè)具體類型更加通用時(shí),泛型才有幫助。

4、怎么用泛型

泛型有三種使用方式:泛型類、泛型接口、泛型方法。

public interface GenricInterface<T> {
    public T getField();
}

public class GenricClass<T> implements GenricInterface<T>{
    private T field;
    public GenricClass(T f) {field=f;}
    public T getField() {return field;}
//  靜態(tài)泛型方法無(wú)法訪問(wèn)類中定義的類型。必須額外聲明
    public static <T> T genricMethod(Class<T> tc) throws InstantiationException, IllegalAccessException{
        T t=tc.newInstance();
        return t;
    }
    public void show1(T t){System.out.println(t.toString());}
    public <E> void show2(E e){System.out.println(e.toString());}
    public <T> void show3(T t){System.out.println(t.toString());}
}

前面說(shuō)過(guò)了泛型無(wú)法通過(guò)new T( )創(chuàng)建對(duì)象實(shí)例,Java的解決方案是使用工廠對(duì)象來(lái)創(chuàng)建新的實(shí)例,最便利的工廠對(duì)象就是Class對(duì)象,可以通過(guò)newInstance()來(lái)創(chuàng)建該類型新對(duì)象。

    public void testGenricMethod(){
        System.out.println("泛型方法測(cè)試----------------------------------------------------------");
        try {
            NormalClass nc= GenricClass.genricMethod(NormalClass.class);
        } catch (InstantiationException | IllegalAccessException e ) {
            e.printStackTrace();
        }
        GenricClass<Integer> g1=new GenricClass<Integer>(10086);
        g1.show1(100);
//      g1.show1(100.1);
        g1.show2(100);      g1.show2(100.1);
        g1.show3(100);      g1.show3(100.1);
    }

泛型通配符

    public void testWildcard(){//通配符測(cè)試
        System.out.println("通配符測(cè)試----------------------------------------------------------");
        GenricClass<Integer> g1=new GenricClass<Integer>(10086);
        GenricClass<Number> g3=new GenricClass<Number>(66.666);
//      show(g1);//參數(shù)不匹配        
        show(g3);
        show2(g1);      show2(g3);
        show3(g1);      show3(g3);
//      show4(g1);      show4(g3);//參數(shù)不匹配   <?>可理解為所有泛型父類<? extends Object>
    }
    public void show(GenricClass<Number> gc){
        System.out.println("show:"+gc.getField());
    }
    public void show2(GenricClass<? extends Number> gc){
        System.out.println("show2:"+gc.getField());
    }
    public void show3(GenricClass<?> gc){
        System.out.println("show3:"+gc.getField());
    }
    public void show4(GenricClass<Object> gc){
        System.out.println("show4:"+gc.getField());
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 泛型是Java 1.5引入的新特性。泛型的本質(zhì)是參數(shù)化類型,這種參數(shù)類型可以用在類、變量、接口和方法的創(chuàng)建中,分別...
    何時(shí)不晚閱讀 3,122評(píng)論 0 2
  • 在之前的文章中分析過(guò)了多態(tài),可以知道多態(tài)本身是一種泛化機(jī)制,它通過(guò)基類或者接口來(lái)設(shè)計(jì),使程序擁有一定的靈活性,但是...
    _小二_閱讀 762評(píng)論 0 0
  • 附上思維導(dǎo)圖。這篇博客主要講了如下知識(shí)點(diǎn)。 看完了《Thinking in Java》的第十五章泛型,著實(shí)被震了一...
    Happioo閱讀 1,172評(píng)論 0 1
  • 關(guān)于作者 吉姆·柯明斯,資深的廣告專家,在多家機(jī)構(gòu)擔(dān)任首席戰(zhàn)略規(guī)劃師。 關(guān)于本書(shū) 本關(guān)于如何說(shuō)服他人的工具書(shū)。想要...
    Wells陸閱讀 949評(píng)論 0 1
  • 沒(méi)有街頭閃爍的霓虹,沒(méi)有塞滿排隊(duì)的車流,更沒(méi)有風(fēng)云激昂的傳說(shuō)。沂蒙一角,蟋蟀略鳴,黑狗稍燥,微風(fēng)漸起,暮色四...
    fc8711f32b28閱讀 177評(píng)論 0 1

友情鏈接更多精彩內(nèi)容