泛型詳解與解析總結


  • tags:泛型
  • categories:筆記
  • date: 2017-06-10 11:24:24

在java代碼開發(fā)中,泛型的使用是非常普遍的袁稽,特別是在集合中扰付。那么,其實java中的泛型并不是真正意義上的新的類型价脾,只是java語法中的語法糖已。便于java編譯器在編譯源代碼的時候進行類型校驗笛匙,今早發(fā)現(xiàn)程序錯誤而已侨把。但是對于我們程序員來說的話,有了泛型妹孙,確實會對我們程序開發(fā)秋柄,無論是代碼可讀性,還是開發(fā)效率都有一定的積極作用蠢正。所以华匾,就打算來分析分析泛型內容,是怎么來的机隙,有什么內容蜘拉,該如何使用。


image

泛型Type與Class

下面可以來討論看看泛型-Type接口-Class類型之間的關系有鹿?

  • 泛型出現(xiàn)之前的類型
    在JDK1.5之前旭旭,沒有引入泛型類型的概念的時候,只有所謂的原始類型(相對于泛型參數(shù)化的List<String>來說葱跋,List就是原始類型)持寄,所有的原始類型都是通過字節(jié)碼文件類Class類進行抽象。java.lang.Class類的一個具體對象就代表一個指定的原始類型娱俺。(eg: String原始類型抽象類即為:String.class....)

  • 泛型出現(xiàn)后的類型
    泛型<>類型出現(xiàn)之后稍味,就擴充了數(shù)據(jù)類型。即在原始類型的基礎上荠卷,添加泛型的特性模庐,就能代表或者說表達更多的數(shù)據(jù)類型。從只有原始類型擴充了參數(shù)化類型(ParameterizedType)油宜,類型變量類型(TypeVariable)掂碱,泛型限定的參數(shù)化類型(含通配符+通配符限定表達式。即 ? extends , super等)慎冤,泛型數(shù)組類型(GenericArrayType)疼燥。

  • 3. 與泛型有關的類型不能和原始類型統(tǒng)一到Class的原因(泛型類型與對應的原始類型對應相同的Class)
    上面這個原因要說的意思是:泛型類型所代表的Class對象與對應的原始類型對應的Class是同一個對象,例如:List<String>,List<Integer>..等等與原始類型List蚁堤,所代表的Class類都是java.util.List醉者。因為會有"類型擦除"原因。

【1】產生泛型擦除的原因
本來新產生的類型+原始類型都應該統(tǒng)一成各自的字節(jié)碼文件Class類型對象披诗,但是由于泛型不是最初的Java的基礎部分撬即,如果真的要加入的真正的泛型,會涉及到JVM指令集的修改藤巢,這樣代價就太大了搞莺。多說一句:在java中的泛型并不是代表著真正的新的類型,只是一個語法糖掂咒,便于類型檢查和編譯器優(yōu)化的手段而已才沧。

【2】Java中如何引入泛型
為了使用泛型的優(yōu)勢而又不真正引入泛型,java采用“泛型擦除”的機制來引入泛型這個語法糖绍刮。所以Java中的泛型僅僅是給編譯器javac使用的温圆,用來確保數(shù)據(jù)的安全性和免去強制類型轉換的麻煩。結果就是孩革,一旦含有泛型聲明和定義使用的代碼地方岁歉,經過編譯完成之后,所有和泛型有關的類型就會被全部擦除膝蜈,也就是被清理掉锅移。(List<String> list = new ArrayLIst<String>() 會編譯成 List list = new ArrayList( ))熔掺。

【3】Class不能表達與泛型有關的類型
由于編譯器的"擦除"機制,就造成了與泛型有關的如參數(shù)化類型非剃,類型變量類型置逻,泛型限定的參數(shù)化類型,數(shù)組類型备绽,都會被全部打回原形券坞,在字節(jié)碼文件中中全部都是泛型擦除后的原始類型,并不存在和自身類型一直的字節(jié)碼文件肺素。所以恨锚,和泛型相關的新擴充進行的類型不能被統(tǒng)一到Class類中,即List<String>并不能用類似List<String>.class這個Class類文件來表示類型倍靡。

【4】 與泛型有關的類型在java中的表示
為了通過反射操作這些類型已迎合實際的開發(fā)需要猴伶,Java就新增加了ParameterizedType,GenericArrayType,TypeVariable,WildcardType這幾種類型來代表不能被歸一到Class類中的類型菌瘫,但是又是和原始類型不同且齊名同等級的類型蜗顽。

【5】 Type接口的引入:統(tǒng)一與泛型有關的類型和原始類型Class

  • 引入Type的原因
    為了程序的擴展性,最終引入了Type接口作為Class,ParameterizedType雨让,GenericArrayType,TypeVariable,WildcardType這幾種類型的公共父接口雇盖。這樣實現(xiàn)了Type接口類型參數(shù),并可以接收以上五種子類的實參或者返回值類型就是Type型的參數(shù)栖忠。
  • Type接口中沒有方法的原因
    從上面看到崔挖,Type接口出現(xiàn)僅僅起到了通過多態(tài)來達到程序類型擴展性提高的作用,并沒有其他的作用庵寞。所有狸相,沒有必要提供任何方法。

泛型種類與使用

在Java中捐川,接口Type用于表示所有類型的高級公共接口脓鹃,也是Class類也實現(xiàn)了該接口。Type類型的所有子類型包括:原始類型古沥,參數(shù)化類型瘸右,數(shù)組類型,類型變量和基本類型岩齿。
Type中包括了以下幾種實現(xiàn):

public interface Type {
}
//說明class類可以轉化為Type類型
public final
    class Class<T> implements  java.lang.reflect.Type...
    
Type(所有子接口)
   -GenericArrayType
   -ParameterizedType
   -TypeVariable<D extends GenericDeclaration>
   -WildcardType

下面分別總結每種類型的含義和使用場景太颤。

參數(shù)化類型-原始類型

在Java中,參數(shù)化類型使用java.lang.reflect.ParameterizedType表示盹沈。其源代碼如下龄章,比較重要的或者說通常使用的是前兩個:

public interface ParameterizedType extends Type {
    //獲取參數(shù)化類型中的實際參數(shù)類型(eg. String.class..)
    Type[] getActualTypeArguments();
    //獲取參數(shù)化類型中的原始類型
    Type getRawType();

下面通過一段示例代碼來說明:

import Java.util.*;
//聲明有泛型的類
public class Pair<T> {
    private final T first;
    private final T second;

    public Pair(T first, T second) {
        this.first = first;
        this.second = second;
    }

    public T first() {
        return first;
    }

    public T second() {
        return second;
    }

    //申明返回List<String>的集合
    public List<String> stringList() {
        return Arrays.asList(String.valueOf(first), String.valueOf(second));
    }

    public static void main(String[] args) {
        Pair p = new Pair<Object>(23, "skidoo");
        for (String s : p.stringList())
            System.out.print(s + " ");
    }
}

上述程序會報錯,錯誤在聲明p變量時候,沒有指明參數(shù)類型做裙。這段程序沒多大實用效果岗憋,僅僅用來說明。
若是在程序中有如下聲明:List<String> list = new ArrayList<String>()的時候菇用,對于List<String>來說捐腿,List集合類型就是原始類型贸辈,集合內部元素類型被參數(shù)固定的List<String>就是參數(shù)化類型,即參數(shù)化類型ParameterizedType也是一種類型鸟废,但是是包含內部元素類型被固化的一種類型悍缠,通常都是基于泛型<>來聲明的卦绣。關于代碼中泛型類型使用,有以下幾點需要說明:

  • Java參數(shù)化類型相對于C++的參數(shù)化類型而言飞蚓,有本質區(qū)別滤港。前者只是編譯器的類型檢查的一種手段,而后者則是真正的不利于原始類型的新的類型趴拧。
  • 一個原生類型很像其對應的參數(shù)化類型溅漾,但是它的所有實例成員都要被替換掉,而替換物就是這些實例成員被擦除掉對應部分之后剩下的東西著榴。具體地說添履,在一個實例方法聲明中出現(xiàn)的每個參數(shù)化的類型都要被其對應的原生部分所取代。我們程序中的變量p是屬于原生類型Pair的脑又,所以它的所有實例方法都要執(zhí)行這種擦除暮胧。這也包括聲明返回List<String>的方法stringList。編譯器會將這個方法解釋為返回原生類型List问麸。
//源代碼中聲明
List<String> list = new ArrayList<Stirng>();
list.add("test");

//編譯器編譯后class字節(jié)反匯編得到如下:
List list = new ArrayList();
list.add(String.valueOf("test");
//也就說明了類型擦出和參數(shù)化類型實際上往衷,僅僅參數(shù)化類型與原始類型差不多,僅僅是參數(shù)化類型可以在我們寫代碼時候严卖,在編譯期間進行類型檢查而已席舍,僅僅是編譯器類型安全檢查的一種機制。
  • 不同的類型參數(shù)組成的泛型類型哮笆,其class的類型都和原始類型的class的類型完全相同来颤。也說明了不同類型參數(shù)組成的參數(shù)化類型之間可以進行強制類型轉換。

接下來疟呐,再看看如何在程序中使用ParameterizedType脚曾。可以通過該類獲取參數(shù)化類型中類型參數(shù)的實際類型启具,也就是對應的Class對象本讥。

public class GenericParamType { 
public static void applyMethod(List<Date> list) throws Exception  
    {  
        Method m = GenericParamType.class.getMethod("applyMethod",List.class);  
        // 其返回是參數(shù)的類型
        Type[] t1 = m.getParameterTypes();
        //其返回的是參數(shù)的參數(shù)化的類型,里面的帶有實際的參數(shù)類型
        Type[] t2 = m.getGenericParameterTypes();  
        Method m2 = GenericParamType.class.getMethod("main",String[].class);  
        //參數(shù)里面如果不是參數(shù)化類型的話,那么 getGenericParameterTypes就返回與 getParameterTypes 一樣   
        Type[] t3 = m2.getGenericParameterTypes();
        Type[] t4 = m2.getParameterTypes();  
        out.println(t1[0]);//interface java.util.List    
        out.println(t2[0]);//java.util.List<java.util.Date>  
        //我們通過 getGenericParameterTypes 得到的是 List<Date>,那么我們怎么能得到它的參數(shù)化類型的實例呢  
        // type 還有好多子接口拷沸,我們通過子接口來操作  
        out.println(t2.getClass());  
        ParameterizedType t = (ParameterizedType)t2[0];//將類型向參數(shù)化類型轉換  
        out.println(t.getClass());  
        out.println(t.getActualTypeArguments()[0]);// 可以得到參數(shù)化類型的參數(shù)實例  
          
    }  

}

若是復合的參數(shù)化類型色查,還可以迭代里面的參數(shù)化類型出來:

public class ReflectDemo {

    
    public static void main(String[] args) throws Exception{
        Proxy target = new ReflectDemo.Proxy();
        
        Method m = target.getClass().getDeclaredMethod("parameter", List.class,String[].class,Integer.class);
        Type[] types = m.getGenericParameterTypes();
        Assert.assertEquals(Modifier.PUBLIC, m.getModifiers());
        Class<?>[] parameterTypes = m.getParameterTypes();
        System.out.println("method's parameter class object>>"+parameterTypes.length);
        for(Type t : types) {
            if(t instanceof ParameterizedType) {
                ParameterizedType pt = (ParameterizedType) t;
                Type[] actypes = pt.getActualTypeArguments();
                for(Type tt : actypes) {
                    if(tt instanceof ParameterizedType){
                        ParameterizedType ptt = (ParameterizedType) tt;
                        Type[] pttype = ptt.getActualTypeArguments();
                        for(Type pttt : pttype) {
                            System.out.println(pttt.toString());
                        }
                    }
                    System.out.println(tt.toString());
                }
            }
        }
        
    }
    
    static class Proxy{
        private Map<String,Object> map;
        public void parameter(List<Map<String,Object>> list,String[] str,Integer it){
            
        }
    }
}

數(shù)組類型

在java中,代表數(shù)組類型的類是GenericArrayType.只有諸如Type[][]...形式的至少有一個[]即代表為數(shù)組的類型才能轉化成GenericArrayType撞芍。內部只有一個方法秧了,用于查詢數(shù)組中的元素類型:

//數(shù)組類接口定義
public interface GenericArrayType extends Type {
    Type getGenericComponentType();
}

public class GenType<E> {

    public String[] str;
    public E[] e1;
    public ArrayList<E>[] ale;
    public E[][] e2;
    //不可轉成GenericArrayType,class [[Ljava.lang.Integer;
    public Integer[][] ins;
    //不可轉成GenericArrayType,class [Ljava.lang.String;
    public String[] str;

    public static void main(String[] args) throws Exception{
        Type type = GenType.class.getDeclaredField("ale").getGenericType();
        System.out.println(type.toString());
        //從上一個輸出可以看到是一個參數(shù)化類型或者類型變量數(shù)組類型序无,才可以強轉
        //并且验毡,基本類型對象數(shù)組也不能轉為數(shù)組類型,因為代表固定class對象
        System.out.println(((GenericArrayType)type).getGenericComponentType());
    }

}
//輸出
java.util.ArrayList<E>[]
java.util.ArrayList<E>

關于這個數(shù)組類型GenericArrayType需要說明的是:

  • 無論從左向右有幾個[]并列帝嗡,這個方法僅僅脫去最右邊的[]之后剩下的內容就作為這個方法的返回值.
  • 在通過反射獲取得到類型是參數(shù)化類型數(shù)組或者是類型變量數(shù)組類型晶通,才可以強轉換為GenericArrayType數(shù)組類型對象,對內部的實際元素類型進行查詢和處理哟玷;而主類型是基本數(shù)據(jù)類型對象或者String類型的數(shù)組狮辽,是不能轉成數(shù)組類型的,因為他們已經是原子類型巢寡。

類型變量

在java中類型變量用類TypeVariable表示喉脖。類型變量接口中有個方法getBounds()是用來獲取上邊界類型,原因是在類型變量定義時候只能使用extends關鍵字進行多邊界限定抑月,而不能使用super树叽,所以關鍵字extends都代表的是類型變量的上邊界。
若是將類型變量具體化爪幻,例如定義一個類Person<E>,那么E就代表這個Person類的類型變量菱皆,變量變量,即為可以變的類型挨稿,可以變就代表我們在創(chuàng)建Person實例的時候仇轻,可以傳入不同類型的變量來進行設置。eg: Person<String>, Person<Integer>..等等奶甘。傳入的類型不同篷店,那么,容器元素的類型也就固化了臭家,在編譯期就能檢查錯誤疲陕。

關于類型邊界上界說明看例子:

public static <E extends Map<String, Date>& Cloneable&Serializable> E methodVI(E e){
        return null;
    }

  • E的第一個上邊界就是Map<String,Date>,是參數(shù)化ParameterizedType類型
  • E的第二個上邊界是Cloneable钉赁,是Class類型
  • 因為類型變量可以通過&進行多個上邊界限定蹄殃,因此上邊界有多個,因此返回值類型是數(shù)組類型[ ]

看看使用例子:

public class GenType<E> {

    public Map<String,Object>[] map;
    public E[] e1;
    public ArrayList<String>[] ale;
    public E[][] e2;
    public Integer[][] ins;//不可轉成GenericArrayType
    public String[] str;//不可轉成GenericArrayType

    public static <E extends Map<String, Date>& Cloneable&Serializable> E methodVI(E e){
        return null;
    }

    public static void main(String[] args) throws Exception{
        Type type = GenType.class.getDeclaredField("e1").getGenericType();
        System.out.println(type.toString());
        System.out.println(((GenericArrayType)type).getGenericComponentType());
        System.out.println(((GenericArrayType)type).getGenericComponentType().getClass());
        //類型變量TypeVariable.getBounds()獲取類型邊界
        System.out.println(((TypeVariable)((GenericArrayType)type).getGenericComponentType()).getBounds()[0]);
    }

}
//輸出
E[]
E
class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
class java.lang.Object

通配符類型

表示通配符類型的類型你踩,表示為wildcardType诅岩,通常用符號?來表示匹配讳苦。通常該類用來限定泛型類型的邊界,包括上界和下界吩谦。

public interface WildcardType extends Type {
    //上界鸳谜,? extends ...
    Type[] getUpperBounds();
    //下界,? super ....
    Type[] getLowerBounds();
}

至于邊界的返回值為什么聲明為Type類型式廷,可以從下面例子中看到:

  • public static void printColl(ArrayList<? extends ArrayList<String>> al){}咐扭,其中通配符表達式是?extends ArrayList<String>,這樣extends后面是?的上邊界,這個上邊界是參數(shù)化類型ParameterizedType滑废。
  • public static <E> void printColl(ArrayList<? extends E> al){}蝗肪,其中通配符表達式是? extends E>,這樣extends后面是?的上邊界,這個上邊界是類型變量TypeVariable類型策严。
  • public static <E> void printColl(ArrayList<? extends E[]> al){}穗慕,其中通配符表達式是? extends E[]>,這樣extends后面是?的上邊界,這個上邊界是類型變量GenericArrayType類型妻导。
  • public static <E> void printColl(ArrayList<? extends Number> al){},其中通配符表達式是? extends Number>,這樣extends后面是?的上邊界怀各,這個上邊界是類型變量Class類型倔韭。

所以,綜上的不同類型瓢对,得到的都是Type接口的子實現(xiàn)類寿酌。

extends與super

  • <? extends T> : 是指上界通配符(Upper Bounds Wildcards)
  • <? super T>: 是指下界通配符(Lower Bounds Wildcards)
  • 子類轉換為父類(小轉大)是隱式的,而父類轉換成子類硕蛹,需要顯示手動強制轉換醇疼。
  • PECS(Producer Extends Consumer Super)原則:
  1. 頻繁往外讀取內容的,適合用上界Extends法焰。
  2. 經常往里插入的秧荆,適合用下界Super。
  • List<? extends E>表示該list集合中存放的都是E的子類型(包括E自身)埃仪,由于E的子類型可能有很多乙濒,但是我們存放元素時實際上只能存放其中的一種子類型(這是為了泛型安全,因為其會在編譯期間生成橋接方法<Bridge_Methods>該方法中會出現(xiàn)強制轉換卵蛉,若出現(xiàn)多種子類型颁股,則會強制轉換失敗)傻丝,例子如下:
List<? extends Number> list=new ArrayList<Number>();
list.add(4.0);//編譯錯誤
list.add(3);//編譯錯誤

上例中添加的元素類型不止一種甘有,這樣編譯器強制轉換會失敗,為了安全葡缰,Java只能將其設計成不能添加元素亏掀。雖然List<? extends E>不能添加元素忱反,但是由于其中的元素都有一個共性--有共同的父類,因此我們在獲取元素時可以將他們統(tǒng)一強制轉換為E類型幌氮,我們稱之為get原則缭受。

  • 對于List<? super E>其list中存放的都是E的父類型元素(包括E),我們在向其添加元素時该互,只能向其添加E的子類型元素(包括E類型)米者,這樣在編譯期間將其強制轉換為E類型時是類型安全的,因此可以添加元素宇智,例子如下:
 List<? super Number> list=new ArrayList<Number>();
 list.add(2.0);
 list.add(3.0);

但是蔓搞,由于該集合中的元素都是E的父類型(包括E),其中的元素類型眾多随橘,在獲取元素時我們無法判斷是哪一種類型喂分,故設計成不能獲取元素,我們稱之為put原則机蔗。實際上蒲祈,我們采用extends,super來擴展泛型的目的是為了彌補例如List<E>只能存放一種特定類型數(shù)據(jù)的不足萝嘁,將其擴展為List<? extends E> 使其可以接收E的子類型中的任何一種類型元素梆掸,這樣使它的使用范圍更廣

    public static void main(String[] args) {
        //裝蘋果的盤子不是裝水果的盤子牙言,不等價
//      Plate<Fruit> fp = new Plate<Apple>(new Apple());
        //Plate<? extends Fruit> 是Plate<Fruit> 以及Plate<Apple>的基類
        Plate<? extends Fruit> fp = new Plate<Apple>(new Apple());
//      fp.setItem(new Apple()); //error
//      fp.setItem(new Fruit()); //error
        Fruit f = fp.getItem();
        f.outf();
        Object of = fp.getItem();
        Apple apple = (Apple) fp.getItem();//父類強制轉化為子類
        apple.outa();
        System.out.println(apple);
        
//      Plate<? super Fruit> sf = new Plate<Apple>(new Apple()); //error
        //sf,getItem() >> generic.Fruit@xxx
        Plate<? super Fruit> sf = new Plate<Fruit>(new Fruit());
        //sf,getItem() >> generic.Apple@xxx
        //強制轉換 sf1 = new Plate<Fruit>((Fruit)new Apple())
        Plate<? super Fruit> sf1 = new Plate<Fruit>(new Apple());
        ((Fruit)sf.getItem()).outf();
        System.out.println(sf1.getItem().getClass());
        ((Apple)sf1.getItem()).outa();
        sf.setItem(new Apple());
    }
//輸出
fruit
apple
generic.Apple@4eb09321
fruit
class generic.Apple
apple

設計這玩意酸钦,除了能讓給程序員加點語法糖,在處理這些集合類型時候咱枉,能夠靈活多變的存取不同類型的對象卑硫;另一方面,也為了程序安全蚕断,在編譯器編譯過程中就要對這些容器中元素類型進行類型檢查欢伏,盡早發(fā)現(xiàn)錯誤并反饋給程序員。

原生類型 和 參數(shù)化類型
反射得到參數(shù)化類型中的類型參數(shù)
Java 泛型 <? super T> 中 super 怎么 理解基括?與 extends 有何不同颜懊?

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市风皿,隨后出現(xiàn)的幾起案子河爹,更是在濱河造成了極大的恐慌,老刑警劉巖桐款,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咸这,死亡現(xiàn)場離奇詭異,居然都是意外死亡魔眨,警方通過查閱死者的電腦和手機媳维,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門酿雪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侄刽,你說我怎么就攤上這事指黎。” “怎么了州丹?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵醋安,是天一觀的道長。 經常有香客問我墓毒,道長吓揪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任所计,我火速辦了婚禮柠辞,結果婚禮上,老公的妹妹穿的比我還像新娘主胧。我一直安慰自己叭首,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布踪栋。 她就那樣靜靜地躺著放棒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪己英。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天吴旋,我揣著相機與錄音损肛,去河邊找鬼。 笑死荣瑟,一個胖子當著我的面吹牛治拿,可吹牛的內容都是我干的。 我是一名探鬼主播笆焰,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼劫谅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嚷掠?” 一聲冷哼從身側響起捏检,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎不皆,沒想到半個月后贯城,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡霹娄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年能犯,在試婚紗的時候發(fā)現(xiàn)自己被綠了鲫骗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡踩晶,死狀恐怖执泰,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情渡蜻,我是刑警寧澤术吝,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站晴楔,受9級特大地震影響顿苇,放射性物質發(fā)生泄漏。R本人自食惡果不足惜税弃,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一纪岁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧则果,春花似錦幔翰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至款青,卻和暖如春做修,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抡草。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工饰及, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人康震。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓燎含,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腿短。 傳聞我的和親對象是個殘疾皇子屏箍,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法橘忱,內部類的語法赴魁,繼承相關的語法,異常的語法鹦付,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 開發(fā)人員在使用泛型的時候尚粘,很容易根據(jù)自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數(shù)敲长,那么如果嘗試...
    時待吾閱讀 1,042評論 0 3
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,254評論 0 16
  • 整體Retrofit內容如下: 1泽铛、Retrofit解析1之前哨站——理解RESTful 2尚辑、Retrofit解析...
    隔壁老李頭閱讀 4,559評論 2 12
  • 鄭老師好樣的,這讓我想起2015年一個下午的情景盔腔,那天陽光明媚杠茬,跟著幾位領導走市場,來到一個感覺不食人間煙火的世界...
    心境意境閱讀 195評論 0 1