<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    戲說Java泛型

    戲說Java泛型 
    Sun在Java 5之后的版本中引入了泛型技術(shù)(Generic).泛型是指具有一個(gè)或多個(gè)類型參數(shù)的類或者是接口.泛型技術(shù)其實(shí)在C++的STL中早已廣泛使用,在Java中泛型主要是用來構(gòu)建安全的集合,我們?cè)谑褂肑CF(Java Collections Framework)時(shí)經(jīng)常碰到它們的身影.當(dāng)然泛型還有很多用處,它可以大大提高程序的可復(fù)用性。但是至少有90%的Java程序員都只在構(gòu)建集合時(shí)使用這種技術(shù).在Java中引入泛型技術(shù)之前,我們使用集合時(shí),可以向其中加入任何對(duì)象,這就造成了很多不安全的因素,例如: 

    //in the main() 
              …… 
    List intList=new ArrayList(); 

    intList.add(new Integer(10)); 
    intList.add(new Integer(20)); 
    intList.add(new Integer(30)); 
    intList.add(new String("Sam")); 

    int sum=getSum(intList); 

             …… 


    public static int getSum(List intListIn){ 
       Iterator i=intList.iterator();     //獲取迭代器對(duì)象 
       int sum=0; 
       while(i.hasNext()){ 
         Integer num=(Integer)i.next();  //將集合中得到的對(duì)象強(qiáng)制轉(zhuǎn)換為Integer,Note:這里最容易出現(xiàn)問題! 
         sum+=num.intValue();            /*進(jìn)行拆箱操作,當(dāng)然在Java5之后的版本這個(gè)動(dòng)作可以自動(dòng)完成,我們這里模擬的是Java1.4,研究泛型我們需要復(fù)古~ 
       }                                  *這是一門新的科學(xué),叫做代碼考古學(xué)^_^ */ 
       return sum; 


    這個(gè)程序會(huì)編譯成功!并且不會(huì)出現(xiàn)警告!但是在運(yùn)行時(shí)會(huì)拋出ClassCastException這種運(yùn)行時(shí)異常,String不能通過Integer的instanceof測(cè)試,并且我們從集合中取出元素時(shí),因?yàn)榉祷氐念愋投际荗bject,我們必須對(duì)其進(jìn)行強(qiáng)制轉(zhuǎn)換,嗯~這個(gè)操作是我最討厭的——不但麻煩,多敲了好幾下鍵盤,而且非常不安全,我不敢確定這個(gè)Object是我所希望轉(zhuǎn)換成的類型,如果真要做這種操作,希望大家都先進(jìn)行一下instanceof測(cè)試,安全第一,受罪第二,不過現(xiàn)在確保安全是為了以后受更少的罪!將來在維護(hù)程序時(shí),你甚至可能會(huì)因?yàn)檫@個(gè)小小的原因而一怒之下產(chǎn)生想重寫整個(gè)程序的沖動(dòng)!嗯~實(shí)不相瞞,我就這樣做過~血的教訓(xùn)! 

    但是有了泛型一切都好了起來,我們可以告訴編譯器每個(gè)集合中接受哪些對(duì)象類型,編譯器會(huì)自動(dòng)為你做轉(zhuǎn)換工作,這樣以來我們?cè)诰幾g時(shí)就知道是否向集合中插入了類型錯(cuò)誤的元素. 

    List<Integer> intList=new ArrayList<Integer>(); 

    現(xiàn)在intList這個(gè)集合就只能夠接受Integer類型的對(duì)象: 
    intList.add(new Integer(12)); 
    如果我們向其中加入一個(gè)非Integer的對(duì)象,那么編譯器將報(bào)錯(cuò)! 


    考慮這種情況: 
    List<E> list=new ArrayList<E>; 
    如果F是E的子類型,list中能添加F類型的對(duì)象嗎?當(dāng)然可以!同數(shù)組一樣,子類都可以加入到父類型的集合中,另外對(duì)于接口也是如此,比如Bird類和Plane類都實(shí)現(xiàn)了一個(gè)Flyable的接口,我們想要在一個(gè)集合中放置所有"具有飛行能力"的對(duì)象,就可以很簡單的這樣做: 
    List<Flyable> flyerList=new ArrayList<Flyable>(); 
    flyerList.add(new Bird()); 
    flyerList.add(new Plane()); 
    這樣很和諧,不是嗎?像List<Object>這種形式的集合當(dāng)然就可以容納天下所有類型的對(duì)象了! 

    您可能會(huì)疑問,List<Object>能夠容納所有的對(duì)象,那么它不就與原生態(tài)(我們將不帶任何泛型信息的類型成為原生態(tài)類型,原生態(tài)是一個(gè)很時(shí)髦的東西,但是在Java中我們要避免它)的List相同了嗎?也就是說: 
    List list=new ArrayList(); 
    List<Object> objList=new ArayList<Object>(); 
    上述這兩行代碼所產(chǎn)生的東西是完全一樣的嗎?其實(shí)它們是有差距的,我們通過一個(gè)小程序來驗(yàn)證: 

            public static void main(String[] args){ 
    List<String>names=new ArrayList<String>(); 
    names.add("Sam"); 
    names.add("Jack"); 
    names.add("James"); 
    names.add("Lucy"); 
    sayAllNames(names); 


    private static void sayAllNames(List list){               //我們?cè)谶@里用的是原生態(tài)集合參數(shù) 
    Iterator iterator=list.iterator(); 
    while(iterator.hasNext()){ 
    System.out.println(iterator.next()); 




    程序運(yùn)行的非常順利!它可以喊出集合中包含的所有名字,同時(shí)我們也看到,我們可以將List<String>傳遞給一個(gè)接收原生態(tài)List的方法.如果你擅長向編譯器"找茬"的話,可能會(huì)發(fā)現(xiàn)這個(gè)地方似乎有一個(gè)漏洞,然后你會(huì)嘗試寫出類似如下的代碼: 

           public static void main(String[] args){ 
    List<String>names=new ArrayList<String>(); 
    names.add("Sam"); 
    names.add("Jack"); 
    names.add("James"); 
    names.add("Lucy"); 
    addElement(names); 


    private static void addElement(List list){ 
    list.add(new Integer(10)); 


    我們將一個(gè)Integer對(duì)象插入到一個(gè)String類型的集合中.測(cè)試一下,程序能成功編譯,但是會(huì)產(chǎn)生警告,如果你是在命令行下使用的javac命令進(jìn)行編譯,就可以看到這條警告:使用了未經(jīng)檢查或不安全的操作.如果使用現(xiàn)代IDE,例如Eclipse,也會(huì)看到用使人很不舒服的黃色曲線標(biāo)識(shí)著list.add(new Integer(10))這條語句.可見編譯器非常不希望我們這樣做!但是之所以能通過編譯,主要是為了保持移植兼容性,與過去的Java代碼保持兼容. 


    泛型最初加入到Java中并不受歡迎.Sun在Java中引入泛型技術(shù)最大的挑戰(zhàn)就是做到使具有類型安全的泛型類和原來的原生態(tài)類能夠協(xié)同工作,然而這樣就會(huì)如上述代碼所示,引起許多棘手的代碼安全問題,編譯器就只能就這個(gè)問題發(fā)出警告,提醒程序員最好不要這樣做.這些安全隱患我們總是在程序運(yùn)行時(shí)才能發(fā)現(xiàn),JVM對(duì)于泛型這種東西毫無概念!泛型概念對(duì)于編譯器而言是嚴(yán)格的,編譯器在編譯具有泛型信息的代碼時(shí),會(huì)對(duì)泛型類型進(jìn)行驗(yàn)證,然后執(zhí)行一個(gè)類型擦除過程,也就是從類字節(jié)碼中去掉這些信息!當(dāng)JVM在運(yùn)行時(shí)就看不到所謂的泛型了,這個(gè)就是編譯器的"泛型陰謀",我們有必要了解這個(gè)事實(shí). 


    下面我們將原生態(tài)的List換成List<Object>,情況會(huì)怎么樣呢? 

             public static void main(String[] args){ 
    List<String>names=new ArrayList<String>(); 
    names.add("Sam"); 
    names.add("Jack"); 
    names.add("James"); 
    names.add("Lucy"); 
    addElement(names); 


    private static void addElement(List<Object> list){ 
    list.add(new Integer(10)); 



    嗯~它會(huì)出錯(cuò)!我們一再強(qiáng)調(diào)泛型是安全的,我們不能把一個(gè)List<String>傳遞給一個(gè)接受List<Object>參數(shù)的方法!如果您對(duì)Java數(shù)組比較熟悉,此時(shí)可能會(huì)產(chǎn)生疑問,您可能會(huì)經(jīng)常碰見這樣的代碼: 
            
            Object[] objects=new Integer[]{1,2,3,4,5,6}; 

    我們可以很正常的將一個(gè)子類型的數(shù)組賦給一個(gè)超類型的數(shù)組的引用,但是我們絕對(duì)不可以這樣做: 
            List<Object>objList=new ArrayList<String>(); 
    編譯器是堅(jiān)決不會(huì)讓你通過的!嗯~你感到泛型不夠人性化是不是?它要是能跟數(shù)組一樣就方便了~但是你看一看下面的程序,也許你就不會(huì)這么想了,相反,你或許還會(huì)認(rèn)為Java中的數(shù)組存在缺陷: 

            public static void main(String[] args){ 
    Integer[] intArray=new Integer[]{1,2,3,4,5}; 
    changeElement(intArray); 


    public static void changeElement(Object[] objects){ 
    objects[0]=new String("I Love Java7");       //Hi!問題出在這兒! 

    嗯~你是不是發(fā)現(xiàn)同上面的某個(gè)程序類似?它同樣可以通過編譯,但是我們?cè)谶\(yùn)行時(shí)發(fā)現(xiàn)它會(huì)產(chǎn)生一個(gè)叫做ArrayStoreException的異常!顧名思義,我們向這個(gè)數(shù)組當(dāng)中放入了它所不能接受的東西.這一切的禍根都是源于Java允許我們可以將一個(gè)子類型的數(shù)組賦給一個(gè)超類型的數(shù)組的引用~然而使用泛型就不會(huì)發(fā)生這種情況,編譯器堅(jiān)決阻止這種情況的存在! 

    數(shù)組同泛型似乎是水火不相容,數(shù)組是具體化的對(duì)象,只有在程序運(yùn)行時(shí)才能搞清楚它們的類型,而對(duì)于泛型,我們前面說過,它僅僅在編譯的時(shí)候才會(huì)存在!基于這個(gè)原因我們不可以創(chuàng)建具有泛型信息的數(shù)組:例如new E[] new List<Object>[] 這些做法都是錯(cuò)誤的!一定要注意! 


    然而有一種神奇的方法能夠?qū)⒎盒蜑樽宇愋偷募蟿?chuàng)遞給泛型為父類型的引用,我們?cè)赪indows下查找文件時(shí)經(jīng)常會(huì)用到通配符,比如"*.jpg"表示所有JPG類型的文件,在Java中也有一套適用于泛型的通配符,下面是一個(gè)運(yùn)用了泛型通配符的程序: 


    import java.util.*; 
    public class Test { 

    public static void main(String[] args){ 
    List<Knight>knights=new ArrayList<Knight>(); 

    knights.add(new Knight()); 
    knights.add(new Knight()); 
    knights.add(new Knight()); 

    doAttack(knights); 


    public static void doAttack(List<? extends Rpg>rpgs){ 
    Iterator<? extends Rpg>iterator=rpgs.iterator(); 
    while(iterator.hasNext()){ 
    iterator.next().commonAttack();  //這里next()方法返回的是Rpg 





    class abstract Rpg{ 
      
            public abstract void commonAttack(); 


    class Knight extends Rpg{ 
        
           public void commonAttack(){ 
               System.out.println("The common attack of the knight is very strong!"); 
           } 


    class Magician extends Rpg{ 

           public void commonAttack(){ 
                System.out.println("The common attack of the magician is very weak"); 
           } 


    我們?cè)谏鲜龀绦蛑泻唵蔚臉?gòu)建了幾個(gè)游戲的角色類,抽象類Rpg及它的子類Knight(騎士)和Magician(術(shù)士),所有的游戲角色都會(huì)進(jìn)行普通攻擊,然而攻擊的能力各不相同,騎士的攻擊強(qiáng)度比較大,而術(shù)士的普通攻擊相對(duì)要弱一些,他們主要依靠高科技的魔法攻擊~基于這個(gè)原則,我們?cè)赗pg的子類中重寫了這個(gè)方法.現(xiàn)在我們要做的是讓一群騎士和術(shù)士進(jìn)行戰(zhàn)斗.用doAttack()方法來號(hào)召他們戰(zhàn)斗.您或許早就注意了doAttack()的參數(shù)很奇怪:List<? extends Rpg> 

    這個(gè)就是前面我們所說的泛型通配符,<? extends Rpg>表示可以接受泛型類型是Rpg或Rpg子類型的集合,并且,很重要的一點(diǎn),千萬不要向這些集合中添加任何元素,否則會(huì)引起編譯錯(cuò)誤,原因很簡單,如果允許添加元素的話,很有可能將一個(gè)術(shù)士插入到一群騎士的隊(duì)伍當(dāng)中!有一個(gè)例外,你可以向其中添加null元素 

    通配符?后的extends不僅代表著子類也代表的接口的實(shí)現(xiàn),比如<? extends Serializable>表示所有實(shí)現(xiàn)泛型類型實(shí)現(xiàn)Serializable接口的集合.嗯~我沒寫錯(cuò),的確是extends,盡管這是一個(gè)接口,記住,沒有<? implements Serializable>這種形式,這就是語法,我們必須遵守 

    除了extends,另外還有一個(gè)泛型通配符關(guān)鍵字super,關(guān)于它的作用,請(qǐng)閱讀下面的程序: 


    import java.util.*; 
    public class Test { 

    public static void main(String[] args){ 
    List<Knight>knights=new ArrayList<Knight>(); 

    knights.add(new Knight()); 
    knights.add(new Knight()); 
    knights.add(new Knight()); 

    List<Rpg>rpgs=new ArrayList<Rpg>(); 

    addKnight(rpgs); 



    public static void addKnight(List<? super Knight>list){ 
    list.add(new Knight()); 





    class abstract Rpg{ 
      
            public abstract void commonAttack(); 


    class Knight extends Rpg{ 
        
           public void commonAttack(){ 
               System.out.println("The common attack of the knight is very strong!"); 
           } 


    class Magician extends Rpg{ 

           public void commonAttack(){ 
                System.out.println("The common attack of the magician is very weak"); 
           } 


    你一眼就會(huì)注意到,我們終于可以用親愛的add()方法來添加不是null的東西了!這都是super的功勞,List<? super Knight>的意思是凡是泛型類型為Knight和Knight超類的集合都能夠接受,在程序中你可以看到。我們可以將新的騎士加入到騎士的隊(duì)伍當(dāng)中,或者是將騎士加入到混合角色的隊(duì)伍當(dāng)中,不會(huì)發(fā)生將騎士插入到專業(yè)的術(shù)士隊(duì)伍當(dāng)中這樣的錯(cuò)誤,因?yàn)榫幾g器會(huì)阻止術(shù)士類型的集合傳遞到這個(gè)增加騎士的方法中 

    然而當(dāng)我們什么關(guān)鍵字都不使用呢?就像這樣List<?> 你認(rèn)為它等同于List<Object>嗎?那么你錯(cuò)了,我們前面說過,為了安全,List<Object>只能接受泛型類型為Object類型的集合,而List<?>可以接受泛型類型為任何類型的集合!List<?>和List<? extends Object>是等同的,大家可以自己寫程序測(cè)試一下!可以繼續(xù)把我的騎士和術(shù)士的故事講下去~ 

    使用通配符時(shí)要注意,通配符只是針對(duì)引用聲明使用,使用new生成對(duì)象時(shí)不可以使用通配符! 
    List<? extends Rpg> rpgs=new ArrayList<Knight>();  //這是正確的 
    List<? extends Rpg> magicians=new ArrayList<? super Magician>();  //這是錯(cuò)誤的! 

    我們說過,應(yīng)用泛型可以大大提高程序的可復(fù)用性,下面我們將學(xué)習(xí)如何創(chuàng)建我們自己的泛型類,比上面的要簡單,至少?zèng)]有那么多的編譯錯(cuò)誤和異常,呵呵,可以把心情放松一下,下面的例子,我們構(gòu)造一個(gè)使用泛型的鏈表節(jié)點(diǎn): 

    class Node<T>{                               
    private T value;                    //節(jié)點(diǎn)所包含的值 
    private Node<T> nextNode;           //節(jié)點(diǎn)所指向的下一個(gè)節(jié)點(diǎn) 

    public Node(T valueIn){ 
    value=valueIn; 
    nextNode=null; 


    public void setValue(T valueIn){ 
    value=valueIn; 

    public T getValue(){ 
    return value; 


    public void setNextNode(Node<T> nodeIn){ 
    nextNode=nodeIn; 

    public Node<T> getNextNode(){ 
    return nextNode; 




    如你所見,T就是泛型的標(biāo)識(shí)符,然后在類中,我們可以像使用正常類一樣使用泛型標(biāo)識(shí)符,在類定義中可以使用多個(gè)泛型標(biāo)識(shí)符: 
    class Map<K,V>{ 
       …… 

    我們也可以使用通配符來指定泛型所允許的范圍: 
    class RpgHolder<T extends Rpg>{       //只允許RPG及其子類 
      …… 


    有時(shí)候我們不需要使用一個(gè)泛型類,我們只需要在普通類中簡單的定義一個(gè)支持泛型的方法: 
    public  <T extends Rpg> void makeRpgList(T t){ 

       List<T> rpgList=new ArrayList<T>(); 
       rpgList.add(t); 



    首先我們要聲明方法的泛型標(biāo)識(shí)符<T extends Rpg>,然后像泛型類那樣在方法中使用泛型 

    Java 5出現(xiàn)之后,學(xué)習(xí)變得越來越困難,泛型技術(shù)是主要的困難因素之一,之所以困難主要是因?yàn)樗c以前的代碼保持兼容,這就大大的增加了復(fù)雜性,您也看到了,前面的那一大堆問題~但是學(xué)習(xí)泛型技術(shù)是很有用的,增加了代碼的可復(fù)用性,以及類型安全.本文主要闡述了一些簡單的理論,大家平時(shí)要多練習(xí),有很多事可以做,比如可以嘗試用泛型去重新實(shí)現(xiàn)一些數(shù)據(jù)結(jié)構(gòu),優(yōu)化一些常用的工具類,你會(huì)發(fā)現(xiàn)這是件非常有趣的事! 

    下面是我自己寫的一個(gè)類似List的集合——Tiny,當(dāng)然比起JCF來在實(shí)際應(yīng)用中性能不是很好,但是包含了基本的集合操作,習(xí)慣了JCF,很多數(shù)據(jù)結(jié)構(gòu)的具體實(shí)現(xiàn)都忘得差不多了~得復(fù)習(xí)了~哈哈~閑著沒事練手~練手~這個(gè)是使用一個(gè)長度可變的數(shù)組來實(shí)現(xiàn)的,大家可以嘗試一下用鏈表來實(shí)現(xiàn)它的另一個(gè)版本LinkedTiny,這樣可以省去變化數(shù)組長度的麻煩~ 
    /*-------------- Iterator.java--------*/ 
    package sam.adt; 

    public interface Iterator<T> { 

    boolean hasNext(); 
    T next(); 


    /*--------------- Tiny.java---------*/ 
    package sam.adt; 
    import java.io.*; 
    public interface Tiny<T> extends Serializable{ 
    void add(T valueIn);                    //將值添加到集合的尾部 
    void remove();                          //刪除集合的最后一個(gè)元素 
    void removeFirst();                     //刪除集合中的第一個(gè)元素 
    void addToHead(T valueIn);              //將值添加到集合的頭部 
    boolean remove(T valueIn);              //刪除值為valueIn的元素 
    boolean add(int indexIn,T valueIn);     //在指定索引處添加值 
    boolean remove(int indexIn);            //刪除指定索引處的元素 
    T get(int indexIn);                     //得到指定索引處的元素 
    int indexOf(T valueIn);                 //獲取指定值的索引 
    boolean replace(int indexIn,T valueIn); //將index處的值替換為value 
    int size();                             //獲取集合中當(dāng)前元素?cái)?shù)目 
    void clear();                           //清除整個(gè)集合中的元素 
    boolean contain(T valueIn);             //測(cè)試集合中是否包含值為valueIn的元素 
    Iterator<T> iterator();                 //返回該集合的迭代器對(duì)象 


    /*-------------- ArrayTiny.java------*/ 
    package sam.adt; 

    public class ArrayTiny<T> implements Tiny<T>{ 

    private static final long serialVersionUID=19891107000000001L; 

    private final int INIT_SIZE=10;              //默認(rèn)初始化數(shù)組大小 
    private Object[] elements;                   //用來存儲(chǔ)數(shù)據(jù)的數(shù)組 
    private int size;                            //集合的邏輯大小 

    //適合ArrayTiny的迭代器 
    private class ArrayIterator implements Iterator<T>{ 

    private int currentPos;    //記錄迭代的位置索引 

    public ArrayIterator(){ 
    currentPos=0; 


    public boolean hasNext() { 
    return currentPos<size; 


    public T next() { 
    T value=(T)elements[currentPos]; 
    currentPos++; 
    return value; 




    public ArrayTiny(){ 
    super(); 
    elements=new Object[INIT_SIZE]; 
    size=0; 


    public ArrayTiny(Iterator<T> iterator){ 
    this(); 
    while(iterator.hasNext()){ 
    addArrayLength(); 
    this.add(iterator.next()); 
    size++; 



    //增加內(nèi)部數(shù)組的長度 
    private void addArrayLength(){ 
    if(size==elements.length){ 
    int newSize=size*2; 
    Object[] tempArray=new Object[newSize]; 
    for(int i=0;i<size;i++){ 
    tempArray[i]=elements[i]; 

    elements=null; 
    System.gc(); 
    elements=tempArray; 


    //減小內(nèi)部數(shù)組的長度 
    private void reduceArrayLength(){ 
    if(size<elements.length/4&&size>INIT_SIZE){ 
    int newSize=Math.max(size*2,INIT_SIZE); 
    Object[] tempArray=new Object[newSize]; 
    for(int i=0;i<size;i++){ 
    tempArray[i]=elements[i]; 

    elements=null; 
    System.gc(); 
    elements=tempArray; 



    public boolean add(int indexIn, T valueIn) { 
    if(indexIn>=0&&indexIn<size){ 
    addArrayLength(); 
    for(int i=size;i>indexIn;i--){ 
    elements[i]=elements[i-1]; 

    elements[indexIn]=valueIn; 
    size++; 

    return false; 


    public void add(T valueIn) { 
    addArrayLength(); 
    elements[size]=valueIn; 
    size++; 


    public void addToHead(T valueIn) { 
    add(0,valueIn); 


    public void clear() { 
    elements=null; 
    elements=new Object[INIT_SIZE]; 


    public boolean contain(T valueIn) { 
    int index=indexOf(valueIn); 
    if(index!=-1)return true; 
    return false; 


    public T get(int indexIn) { 
    if(indexIn>=0&&indexIn<size){ 
    return (T)elements[indexIn]; 

    return null; 


    public int indexOf(T valueIn){ 
    for(int i=0;i<size;i++){ 
    if(elements[i].equals(valueIn))return i; 

    return -1; 


    public Iterator<T> iterator() { 
    return new ArrayIterator(); 


    public void remove() { 
    elements[size-1]=null; 
    size--; 
    reduceArrayLength(); 


    public boolean remove(int indexIn) { 
    if(indexIn>=0&&indexIn<size){ 
    for(int i=indexIn;i<size;i++){ 
    elements[i]=elements[i+1]; 

    size--; 
    reduceArrayLength(); 
    return true; 

    return false; 


    public boolean remove(T valueIn) { 
    int index=indexOf(valueIn); 
    return remove(index); 


    public void removeFirst() { 
    remove(0); 


    public boolean replace(int indexIn, T valueIn) { 
    if(indexIn>=0&&indexIn<size){ 
    elements[indexIn]=valueIn; 

    return false; 


    public int size() { 
    return size; 



    posted on 2010-07-31 16:04 遲宏澤 閱讀(2342) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    <2010年7月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    統(tǒng)計(jì)

    常用鏈接

    留言簿

    隨筆檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲国产精品久久| 午夜亚洲国产理论片二级港台二级 | 久久精品免费一区二区| 在线观看亚洲AV日韩A∨| 亚洲日韩中文在线精品第一| 久久精品一区二区免费看| 在线亚洲午夜片AV大片| 成人免费的性色视频| 亚洲黄色高清视频| 久久w5ww成w人免费| 亚洲av纯肉无码精品动漫| 亚洲成AV人片一区二区密柚| 最近免费中文字幕大全视频| 一级一看免费完整版毛片| 亚洲人成人77777在线播放 | 亚洲国产成人精品无码久久久久久综合 | 国产综合免费精品久久久| 久久精品亚洲乱码伦伦中文| 在线观看免费亚洲| 99精品全国免费观看视频 | 久久精品国产亚洲| 桃子视频在线观看高清免费视频 | 免费精品国产自产拍在线观看| 亚洲Av无码专区国产乱码DVD| 成人免费午夜在线观看| 在线毛片片免费观看| 亚洲日本va午夜中文字幕一区| 国产成人无码区免费A∨视频网站 国产成人涩涩涩视频在线观看免费 | 91精品国产免费| www成人免费观看网站| 久久夜色精品国产噜噜亚洲a| 久久精品国产亚洲麻豆| 四虎永久精品免费观看| 亚洲天堂免费在线| 久久99精品国产免费观看| 成在线人直播免费视频| 亚洲国产精品无码久久久秋霞1| 久久亚洲精品无码aⅴ大香| 亚洲色中文字幕无码AV| 亚洲免费观看在线视频| 美女被免费网站91色|