Java泛型總結(jié)

Java泛型總結(jié)#

泛型是什么##

從本質(zhì)上講闸度,泛型就是參數(shù)化類型猾骡。泛型十分重要瑞躺,使用該特性可以創(chuàng)建類敷搪、接口以及方法,并且可以使用類型參數(shù)來指定類型幢哨。沒有泛型以前赡勘,對(duì)于不確定的類型常常使用Object類,因?yàn)镺bject類是其他任何類的超類捞镰,可以創(chuàng)建任何類型的對(duì)象狮含。但是缺點(diǎn)也十分明顯,不能以類型安全的形式工作曼振。泛型提供了以前沒有的類型安全性几迄,簡化處理過程,不需要像使用Object類時(shí)需要類型轉(zhuǎn)換冰评,泛型提供自動(dòng)的隱式類型轉(zhuǎn)換映胁。

一個(gè)簡單的泛型實(shí)例##

創(chuàng)建Gen泛型類,類型參數(shù)為T甲雅。T可以是任何引用類型解孙,使用時(shí),可以傳遞任何引用類型抛人。T在此處相當(dāng)于就是一個(gè)占位符弛姜,其可以是任意引用類型。

public class Gen <T> {
    T ob;
    Gen(T ob){
        this.ob = ob;
    }

    T getOb(){
        return ob;
    }

    //顯示類型參數(shù)的類型
    void showType(){
        System.out.println("T's Type is: " + ob.getClass().getName());
    }
}

使用泛型妖枚,用具體的類型替換占位符T廷臼。

public class GenDemo {
    public static void main(String[] args) {
        Gen<String> strGen = new Gen<>("string type");
        strGen.showType();

        Gen<Integer> intGen = new Gen<>(100);
        intGen.showType();
    }
}

執(zhí)行結(jié)果:

T's Type is: java.lang.String
T's Type is: java.lang.Integer

Process finished with exit code 0

可以看出,T的類型就是在使用泛型時(shí)傳遞的類型參數(shù)的類型绝页。

Gen<String> strGen = new Gen<>("string type");

上面的語句將表示T的類型為String荠商,此語句也可以聲明為下面的形式,但是上面的形式更加簡潔续誉,從jdk 1.7開始可以去掉構(gòu)造器中的類型參數(shù)莱没,泛型提供了類型推斷功能,因此可以省略酷鸦,這也被稱為泛型的菱形語法饰躲。

Gen<String> strGen = new Gen<String>("string type");

泛型只適用引用類型###

當(dāng)聲明泛型時(shí),傳遞的參數(shù)必須是引用類型臼隔,使用簡單類型是非法的嘹裂。比如下面的聲明:

Gen<int> genInt = new Gen<int>(100);//非法的

基于不同類型參數(shù)的泛型類型是不同的###

Gen<String> strGen = new Gen<>("string type");
Gen<Integer> intGen = new Gen<>(100);

上面的兩行代碼聲明的泛型類型是不同的

strGen == intGen

上面的代碼會(huì)出現(xiàn)編譯錯(cuò)誤。

泛型類型提升類型安全性的原理

我們先來看一個(gè)不使用泛型的例子躬翁。

public class Nor {
    Object obj;

    Nor(Object obj){
        this.obj=obj;
    }

    Object getObj(){
        return obj;
    }
}

首先編譯器不知道任何關(guān)于構(gòu)造器傳入的類型信息焦蘑,這是一件壞事盯拱。其二盒发,對(duì)于數(shù)據(jù)需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換例嘱。

public class NorDemo {

    public static void main(String[] args) {
        
        Nor intNor = new Nor(11);

        int a = (Integer) intNor.getObj();

        String str = (String) intNor.getObj();
    }
}

上面的代碼可以看出,inNor.getObj()返回類型是Integer類型宁舰,但是卻賦值給了String型拼卵,但是編譯時(shí)能通過,因?yàn)榫幾g器不知道Object的類型蛮艰,但是很遺憾腋腮,運(yùn)行時(shí)肯定會(huì)有類型轉(zhuǎn)換的問題。

運(yùn)行上面的代碼拋出ClassCastException異常

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at simpledemo.NorDemo.main(NorDemo.java:11)

但是使用泛型就不會(huì)發(fā)生以上情況壤蚜,泛型顯示的聲明了類型參數(shù)即寡,這讓開發(fā)人員和編譯器都知道參數(shù)的類型。

帶有兩個(gè)類型參數(shù)的泛型類

public class TwoGen <T,V>{
    T obj1;
    V obj2;

    TwoGen(T obj1, V obj2){
        this.obj1 = obj1;
        this.obj2=obj2;
    }

    T getObj1(){
        return obj1;
    }

    V getObj2(){
        return obj2;
    }
}

和一個(gè)類型參數(shù)的泛型類差不多袜刷,菱形框里的參數(shù)可以有多個(gè)聪富,如果類型參數(shù)總是一樣,那就沒有必要聲明多個(gè)著蟹。比如下面的代碼墩蔓,聲明一個(gè)類型參數(shù)就夠了。

TwoGen<String,String> t = new TwoGen<>("aaa", "bbb");

有界類型##

從前面的例子可以看出萧豆,類型參數(shù)可以是任意的奸披,但是往往一件事沒有約束并不是好的。如果現(xiàn)在我們想寫一個(gè)加法器涮雷,讓任意的兩個(gè)數(shù)字相加阵面,這些數(shù)字可以是整型、浮點(diǎn)型的洪鸭,如果使用泛型的方式膜钓,根據(jù)前面的經(jīng)驗(yàn),可以這樣編碼

public class Caculator <T> {
    T a;
    T b;

    T getSum(T a, T b){
        return a+b;//錯(cuò)誤
    }
}

那么問題來了卿嘲,因?yàn)門可以任意類型的颂斜,而加運(yùn)算只針對(duì)與數(shù)字和字符串連接,編譯器并不知道T的類型拾枣,所以就更不知道這個(gè)+號(hào)是用來干嘛的了沃疮。

為了處理這種情況java提供了類型邊界,我們先來看使用類型邊界的實(shí)現(xiàn):

public class Caculator <T extends Number> {

    double sum;

    double getSum(T a, T b){
        sum = a.doubleValue()+b.doubleValue();
        return sum;
    }

    public static void main(String[] args) {
        Caculator<Integer> integerCaculator = new Caculator<>();
        double a = integerCaculator.getSum(3,4);
        System.out.println(a);

        Caculator<Float> floatCaculator =  new Caculator<>();
        double b = floatCaculator.getSum(9.0f,10.45f);
        System.out.println(b);

        Caculator<Double> doubleCaculator = new Caculator<>();
        double c = doubleCaculator.getSum(1.0,2.4);
        System.out.println(c);
    }


}

結(jié)果:

7.0
19.449999809265137
3.4
Process finished with exit code 0

分析:

下面的代碼說明類型參數(shù)為Number的子類梅肤,也就是說將T的范圍限制在Number和Number的子類中

Caculator <T extends Number>

所以才可以使用a.doubleValue()方法司蔬,因?yàn)門繼承自Number。還有一個(gè)好處就是可以防止傳入不能處理的類型姨蝴,比如String俊啼,因?yàn)镾tring并不是Number子類,編譯會(huì)報(bào)錯(cuò)左医。

當(dāng)然也可以擴(kuò)展一個(gè)或多個(gè)接口授帕,使用&連接

Class SomeClass <T extends SuperClass & Interface1 &Interface2> { ...}

綜上同木,Number就是類型參數(shù)的上界,T類型只能是Number和Number的子類跛十。

通配符參數(shù)##

上例中彤路,我們使用了getSum()方法來求不同數(shù)字類型的兩個(gè)數(shù)之和,如果要擴(kuò)展Caculator類芥映,讓其比較兩個(gè)數(shù)之和是否相等洲尊。按照上面思路我們可以這樣做:

public class Caculator <T extends Number> {

    double sum;

    double getSum(T a, T b){
        sum = a.doubleValue()+b.doubleValue();
        return sum;
    }

    Boolean isEquals(Caculator<T> caculator){
        return this.sum == caculator.sum;
    }

    public static void main(String[] args) {
        Caculator<Integer> integerCaculator = new Caculator<>();
        double a = integerCaculator.getSum(3,4);
        System.out.println(a);

        Caculator<Double> doubleCaculator1 = new Caculator<>();
        double d = doubleCaculator.getSum(3.0,4.0);
        System.out.println(d);
        //非法,因?yàn)門的類型為Integer奈偏,isEquals()方法中傳入的類型為Caculator<String>.
        integerCaculator.isEquals(doubleCaculator1);
      
        Caculator<Integer> integerCaculator1 = new Caculator<>();
        double e = integerCaculator.getSum(1,6);
        System.out.println(e);
        //合法坞嘀,因?yàn)閭魅氲念愋蛥?shù)都是Integer
        integerCaculator.isEquals(integerCaculator1);
    }


}

從上面的代碼可以看出,上面的類值能適用于參數(shù)類型相等的情況惊来,如果我們要比較3+4和2.5+4.5姆吭,此方法就不適用了。為了實(shí)現(xiàn)更好的一般性唁盏,我們可以使用通配符内狸。

先來看一下用通配符怎么實(shí)現(xiàn)

public class Caculator <T extends Number> {

    double sum;

    double getSum(T a, T b){
        sum = a.doubleValue()+b.doubleValue();
        return sum;
    }

    //注意,這里修改了類型參數(shù)厘擂,把T換成了?
    Boolean isEquals(Caculator<?> caculator){
        return this.sum == caculator.sum;
    }

    public static void main(String[] args) {
        Caculator<Integer> integerCaculator = new Caculator<>();
        double a = integerCaculator.getSum(11,3);
        System.out.println(a);

        Caculator<Double> doubleCaculator = new Caculator<>();
        double b = doubleCaculator.getSum(11.0, 3.0);
        System.out.println(b);
        System.out.println(doubleCaculator.isEquals(integerCaculator));

        Caculator<Integer> integerCaculator2=new Caculator<>();
        double c  = integerCaculator2.getSum(2,12);
        System.out.println(c);
        System.out.println(integerCaculator.isEquals(integerCaculator2));

    }


}

通配符----昆淡?,顧名思義就是可以給泛型類傳遞任何類型的類型參數(shù)刽严,通配符對(duì)參數(shù)類型沒有限制昂灵,限制條件是<T extends SuperClass>決定的。

有界通配符###

下圖定義三個(gè)坐標(biāo)類舞萄,F(xiàn)ourD繼承自TreeD眨补,ThreeD繼承自TwoD。就是說倒脓,四維坐標(biāo)可以有三維坐標(biāo)和二維坐標(biāo)的行為撑螺,三維坐標(biāo)可以有二維坐標(biāo)的行為。

class TwoD {
    int x;
    int y;

    public TwoD(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

class ThreeD extends TwoD {
    int z;

    public ThreeD(int x, int y, int z) {
        super(x, y);
        this.z = z;
    }
}


class FourD extends ThreeD {
    int t;

    public FourD(int x, int y, int z, int t) {
        super(x, y, z);
        this.t = t;
    }
}

Coords類把坐標(biāo)類型限制在TwoD以及TwoD的子類崎弃。

BoundeWidecard類定義了三個(gè)打印坐標(biāo)的方法:

  • show2D(Coords<? extends TwoD> coords)方法可以打印TwoD甘晤、ThreeD和FourD中任意一個(gè)類的xy坐標(biāo)。
  • show3D(Coords<? extends ThreeD> coords)方法可以打印ThreeD和FourD中任意一個(gè)類的xyz坐標(biāo)饲做。
  • show4D(Coords<? extends FourD> coords)方法可以打印FourD中的xyzt坐標(biāo)线婚。

class Coords<T extends TwoD> {
    T ob;

    Coords(T ob) {
        this.ob = ob;
    }
}

public class BoundeWildcard {
    static void show2D(Coords<? extends  TwoD> coords) {
        System.out.println("2d, x: " + coords.ob.x + " y: " + coords.ob.y);
    }

    static void show3D(Coords<? extends ThreeD> coords) {
        System.out.println("3d, x: " + coords.ob.x + " y: " + coords.ob.y + "z: " + coords.ob.z);
    }

    static void show4D(Coords<? extends FourD> coords) {
        System.out.println("4d, x: " + coords.ob.x + " y: " + coords.ob.y + "z: " + coords.ob.z + "z: " + coords.ob.t);
    }

    public static void main(String[] args) {
        Coords twoD = new Coords(new TwoD(11,22));
        Coords threeD = new Coords(new ThreeD(111,222,333));
        Coords fourD = new Coords(new FourD(1111,2222,3333,4444));

        show2D(twoD);
        show3D(threeD);
        show4D(fourD);

        //show3D(twoD); //運(yùn)行時(shí)錯(cuò)誤
        show3D(threeD);
        show3D(fourD);

        //show4D(twoD); //運(yùn)行時(shí)錯(cuò)誤
        //show4D(threeD); //運(yùn)行時(shí)錯(cuò)誤
        show4D(fourD);

    }
}

結(jié)果

2d, x: 11 y: 22
3d, x: 111 y: 222z: 333
4d, x: 1111 y: 2222z: 3333z: 4444
3d, x: 111 y: 222z: 333
3d, x: 1111 y: 2222z: 3333
4d, x: 1111 y: 2222z: 3333z: 4444

Process finished with exit code 0

泛型方法

下面我們創(chuàng)建一個(gè)泛型方法來判斷一個(gè)對(duì)象是都存在于一個(gè)對(duì)象數(shù)組中。

public class GenMethDemo {
    static <T extends Comparable<T>, V extends  T> boolean isIn(T x, V[] y){
        for (V v : y) {
            if ((x.compareTo(v))==0)
                return true;
        }
        return false;
    }

    public static void main(String[] args) {
        int x =2;
        Integer [] x_array = {1,2,3,4,5,6}; //不能用簡單類型創(chuàng)建
        Integer [] y_array = {1,3,4,5,6};
        boolean flag;

        flag = isIn(x,x_array);
        System.out.println("2 is in x_array: " + flag);

        flag = isIn(x,y_array);
        System.out.println("2 is in y_array: " +flag);


    }
}

說明參數(shù)類型T都要實(shí)現(xiàn)Comparable<T>泛型接口盆均,這樣才能使用compareTo方法來比較兩個(gè)對(duì)象塞弊。V extends T表示V是T或者是T的子類,這樣聲明了兼容的數(shù)據(jù)類型,方便比較游沿。

泛型構(gòu)造函數(shù)##

可以將構(gòu)造函數(shù)泛型化饰抒,即使不是泛型類。

public class GenConstructor {
    double val;

    <T extends Number> GenConstructor(T val){
        this.val = val.doubleValue();
    }

    void showVal(){
        System.out.println("val: "+ val);
    }

    public static void main(String[] args) {
        GenConstructor genConstructor = new GenConstructor(11);
        GenConstructor genConstructor1 = new GenConstructor(11.3f);

        genConstructor.showVal();
        genConstructor1.showVal();
    }
}

結(jié)果:

val: 11.0
val: 11.300000190734863

Process finished with exit code 0

泛型接口##

一般來說奏候,泛型接口的聲明和泛型類的聲明是一樣的。值得注意的是唇敞,因?yàn)閷?shí)現(xiàn)類需要實(shí)現(xiàn)泛型接口蔗草,所以實(shí)現(xiàn)類必須是泛型類。下面是一個(gè)泛型接口和實(shí)現(xiàn)的例子:

public interface GenInterface <T extends Comparable<T>> {
}

class Gen<T extends Comparable<T>> implements GenInterface<T>{

}

因?yàn)閷?shí)現(xiàn)類實(shí)現(xiàn)了接口疆柔,實(shí)現(xiàn)類就必須和接口的參數(shù)類型相同(包含接口的參數(shù)類型)咒精,所以在implements子句中就不用再將參數(shù)類型全部寫全,而且這樣是錯(cuò)誤的:

class Gen<T extends Comparable<T>> implements GenInterface<T extends Comparable<T>>{//非法
}

使用泛型接口有兩個(gè)優(yōu)勢:

  • 針對(duì)不同類型實(shí)現(xiàn)
  • 可以給類型設(shè)置邊界

使用泛型的一些限制

不能實(shí)例化類型參數(shù)###

class Gen<T>{
    T ob;
    Gen(){
        this.ob = new T(); //非法
    }
}

很明顯旷档,這里T只是一個(gè)占位符模叙,系統(tǒng)不知道具體的類型。

對(duì)靜態(tài)成員的一些限制###

class Wrong<T>{
    static T ob; //非法鞋屈,不能聲明T類型的靜態(tài)變量
    //非法范咨,靜態(tài)方法返回值不能是T
    static T getOb(){ 
        return ob;
    }
}

盡管不能聲明某些帶有類型參數(shù)的靜態(tài)成員,但是可以聲明泛型方法厂庇。下面的泛型方法用來判斷一個(gè)對(duì)象是否存在于另外一個(gè)對(duì)象中渠啊,因?yàn)椴荒芘袛囝愋偷木唧w類型,所以使用泛型方法权旷,可以看出泛型方法的使用范圍更加廣泛替蛉,這就是泛型的“泛”的體現(xiàn)。

public class GenMethDemo {
    static <T extends Comparable<T>, V extends  T> boolean isIn(T x, V[] y){
        for (V v : y) {
            if ((x.compareTo(v))==0)
                return true;
        }
        return false;
    }

    public static void main(String[] args) {
        int x =2;
        Integer [] x_array = {1,2,3,4,5,6}; //不能用簡單類型創(chuàng)建
        Integer [] y_array = {1,3,4,5,6};
        boolean flag;

        flag = isIn(x,x_array);
        System.out.println("2 is in x_array: " + flag);

        flag = isIn(x,y_array);
        System.out.println("2 is in y_array: " +flag);
    }
}

泛型類層次##

和非泛型類一樣拄氯,泛型類可以繼承和被繼承躲查。但是需要注意,和非泛型類不一樣的是:泛型類需要向上傳遞超類需要類型參數(shù)译柏,就想非泛型類中構(gòu)造器向上傳遞一樣镣煮。

泛型超類##

泛型超類示例:

public class Gen <T> {
    public static void main(String[] args) {
        SubGen<String> subGen = new SubGen<>();
    }
}

class SubGen<T> extends Gen<T>{

}

下面的代碼向超類傳遞了參數(shù)類型String,對(duì)于Gen來說鄙麦,他的參數(shù)類型為String怎静。

SubGen<String> subGen = new SubGen<>()

還要注意的是,泛型子類除了將類型參數(shù)傳遞給泛型超類黔衡,再也沒有使用類型參數(shù)T蚓聘。所以,即使泛型超類的子類不必泛型化盟劫,其也必須指定泛型超類需要的類型參數(shù)夜牡。

當(dāng)然,泛型子類也可以添加自身的類型參數(shù)

class SubGen<T,V> extends Gen<T>{

}

泛型子類###

非泛型類可以是泛型類的超類。

public class Gen  {
    
}

class SubGen<T> extends Gen{

}

強(qiáng)制轉(zhuǎn)換

需要注意的是塘装,使用強(qiáng)制轉(zhuǎn)換時(shí)兩個(gè)泛型類的類型必須兼容急迂,并且類型參數(shù)也要相同。

類型擦除##

通常蹦肴,我們不需要知道Java源碼轉(zhuǎn)化為對(duì)象代碼的細(xì)節(jié)僚碎,但是對(duì)于泛型而言大致了解這個(gè)過程是很重要的,這有助于我們理解泛型的工作機(jī)制阴幌。

影響泛型如何添加到Java的一個(gè)最重要的約束:就是要和之前的Java版本兼容勺阐,簡單的說就是要和之前的非泛型代碼兼容,對(duì)Java語法和虛擬機(jī)做的修改不能破壞以前的代碼矛双。為了實(shí)現(xiàn)泛型渊抽,Java使用了類型擦除。

總的來說议忽,運(yùn)行時(shí)沒有參數(shù)類型懒闷,所有的類型參數(shù)都會(huì)轉(zhuǎn)化為具體的類型,如果沒有界定類型栈幸,則用Object表示愤估。

橋接方法###

有時(shí)候,編譯器需要添加一些橋接方法速址,比如泛型子類重寫方法的類型擦除灵疮,不能產(chǎn)生超類中方法的類型擦除。對(duì)于這種情況壳繁,會(huì)生成使用超類類型擦除的方法震捣,并且這個(gè)方法調(diào)用具有由子類指定的類型擦除的方法。當(dāng)然闹炉,橋接方法只會(huì)在字節(jié)碼級(jí)別發(fā)生蒿赢,你不會(huì)看到,也不能使用渣触。

比如在父類中有一個(gè)getOb()方法

public class Gen<T> {
    T ob;

    Gen(T ob){
        this.ob = ob;
    }

    T getOb(){
        return ob;
    }

}

但是這個(gè)泛型類的子類重寫了該方法

class Gen2<String> extends Gen<String>{

    Gen2(String ob) {
        super(ob);
    }

    String  getOb(){
        System.out.println("aaaa");
        return ob;
    }

}

對(duì)于上面的兩段代碼羡棵,子類Gen2擴(kuò)展了Gen,但是使用特定于String的Gen版本嗅钻,同時(shí)Gen2還重寫了getOb()方法皂冰。所有這些都是可以接受的,但是對(duì)于類型擦除卻稍顯麻煩养篓。本來期待的下面的方法:

T getOb(){
    return ob;    
}

為了處理這個(gè)問題秃流,編譯器生成一個(gè)橋接方法,這個(gè)橋接方法調(diào)用String版本的那個(gè)簽名柳弄。因此如果檢查有javap生成的Gen2類文件舶胀,就會(huì)看到下面的方法:

java.lang.String getOb();
java.lang.Object getOb(); //橋接方法

對(duì)于上面兩個(gè)方法,唯一不同的就是返回類型,通常來講這是錯(cuò)誤的嚣伐,因?yàn)檫@不是源碼引起的糖赔,JVM會(huì)正確的處理它。

對(duì)泛型數(shù)組的一些限制

不能實(shí)例化參數(shù)類型的數(shù)組轩端,這和不能實(shí)例化參數(shù)類型的對(duì)象類似放典。

class Gen<T extends Number> {
    T[] a;
//    a = {1,2,3};//錯(cuò)誤,不能初始化
    Gen(T[] a){
//        this.a = new T[10];//錯(cuò)誤,不能實(shí)例化
        this.a=a;//可以賦值
    }
}

Java 8官方教程說指定類型參數(shù)的泛型數(shù)組不能實(shí)例化基茵。

public class Restriction {
    public static void main(String[] args) {
        Integer[] integers = {1,2,3,4,5,6};

        Gen<Integer> gen[] = new Gen<Integer>[10]; //編譯錯(cuò)誤
        Gen<?> gen1[] = new Gen<Integer>[10];//可以通過


    }
}

由于泛型內(nèi)容比較多奋构,如有遺漏請(qǐng)?jiān)谟懻搮^(qū)補(bǔ)充,本文會(huì)持續(xù)更新修改耿导,歡迎關(guān)注声怔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末态贤,一起剝皮案震驚了整個(gè)濱河市舱呻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悠汽,老刑警劉巖箱吕,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異柿冲,居然都是意外死亡茬高,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門假抄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怎栽,“玉大人,你說我怎么就攤上這事宿饱⊙椋” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵谬以,是天一觀的道長强饮。 經(jīng)常有香客問我,道長为黎,這世上最難降的妖魔是什么邮丰? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮铭乾,結(jié)果婚禮上剪廉,老公的妹妹穿的比我還像新娘。我一直安慰自己炕檩,他們只是感情好妈经,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般吹泡。 火紅的嫁衣襯著肌膚如雪骤星。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天爆哑,我揣著相機(jī)與錄音洞难,去河邊找鬼。 笑死揭朝,一個(gè)胖子當(dāng)著我的面吹牛队贱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播潭袱,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柱嫌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屯换?” 一聲冷哼從身側(cè)響起编丘,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎彤悔,沒想到半個(gè)月后嘉抓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晕窑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年抑片,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杨赤。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡敞斋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疾牲,到底是詐尸還是另有隱情植捎,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布说敏,位于F島的核電站鸥跟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盔沫。R本人自食惡果不足惜医咨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望架诞。 院中可真熱鬧拟淮,春花似錦、人聲如沸谴忧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至委造,卻和暖如春戳鹅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昏兆。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工枫虏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爬虱。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓隶债,卻偏偏與公主長得像,于是被迫代替她去往敵國和親跑筝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子死讹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一、泛型簡介1.引入泛型的目的 了解引入泛型的動(dòng)機(jī)曲梗,就先從語法糖開始了解赞警。 語法糖 語法糖(Syntactic S...
    Android進(jìn)階與總結(jié)閱讀 1,029評(píng)論 0 9
  • 1、為什么使用泛型 泛型是指參數(shù)化類型的能力稀并〗銎模可以定義帶有泛型類型的類或類单默,隨后編譯器會(huì)使用具體的類型來代替它碘举。使...
    追逐地平線的甘閱讀 444評(píng)論 0 1
  • 代碼github地址 泛型不是協(xié)變的,數(shù)組與集合類之間的區(qū)別## 雖然將集合看作是數(shù)組的抽象會(huì)有所幫助搁廓,但是數(shù)組還...
    天外之石閱讀 334評(píng)論 0 0
  • 我們知道引颈,使用變量之前要定義,定義一個(gè)變量時(shí)必須要指明它的數(shù)據(jù)類型境蜕,什么樣的數(shù)據(jù)類型賦給什么樣的值蝙场。 假如我們現(xiàn)在...
    今晚打肉山閱讀 982評(píng)論 0 1
  • 泛型是jdk1.5里出現(xiàn)的一個(gè)非常重要的功能,之前一直只是會(huì)使用一點(diǎn)泛型粱年,但是對(duì)泛型一些復(fù)雜的使用形式總是把握不準(zhǔn)...
    天蝎scorpion閱讀 298評(píng)論 0 0