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

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

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

    posts - 73,  comments - 55,  trackbacks - 0
    JAVA中的傳遞都是值傳遞嗎?有沒有引用傳遞呢?

    在回答這兩個問題前,讓我們首先來看一段代碼:
    Java代碼 復制代碼
    1. public class ParamTest {   
    2.     // 初始值為0   
    3.     protected int num = 0;   
    4.   
    5.     // 為方法參數重新賦值   
    6.     public void change(int i) {   
    7.          i = 5;   
    8.      }   
    9.   
    10.     // 為方法參數重新賦值   
    11.     public void change(ParamTest t) {   
    12.          ParamTest tmp = new ParamTest();   
    13.          tmp.num = 9;   
    14.          t = tmp;   
    15.      }   
    16.   
    17.     // 改變方法參數的值   
    18.     public void add(int i) {   
    19.          i += 10;   
    20.      }   
    21.   
    22.     // 改變方法參數屬性的值   
    23.     public void add(ParamTest pt) {   
    24.          pt.num += 20;   
    25.      }   
    26.   
    27.     public static void main(String[] args) {   
    28.          ParamTest t = new ParamTest();   
    29.   
    30.          System.out.println("參數--基本類型");   
    31.          System.out.println("原有的值:" + t.num);   
    32.         // 為基本類型參數重新賦值   
    33.          t.change(t.num);   
    34.          System.out.println("賦值之后:" + t.num);   
    35.         // 為引用型參數重新賦值   
    36.          t.change(t);   
    37.          System.out.println("運算之后:" + t.num);   
    38.   
    39.          System.out.println();   
    40.   
    41.          t = new ParamTest();   
    42.          System.out.println("參數--引用類型");   
    43.          System.out.println("原有的值:" + t.num);   
    44.         // 改變基本類型參數的值   
    45.          t.add(t.num);   
    46.          System.out.println("賦引用后:" + t.num);   
    47.         // 改變引用類型參數所指向對象的屬性值   
    48.          t.add(t);   
    49.          System.out.println("改屬性后:" + t.num);   
    50.      }   
    51. }  

    這段代碼的運行結果如下:
    1. 參數--基本類型
    2. 原有的值:0
    3. 賦值之后:0
    4. 運算之后:0

    5. 參數--引用類型
    6. 原有的值:0
    7. 賦引用后:0
    8. 改屬性后:20

    從上面這個直觀的結果中我們很容易得出如下結論:
    1. 對于基本類型,在方法體內對方法參數進行重新賦值,并不會改變原有變量的值。
    2. 對于引用類型,在方法體內對方法參數進行重新賦予引用,并不會改變原有變量所持有的引用。
    3. 方法體內對參數進行運算,不影響原有變量的值。
    4. 方法體內對參數所指向對象的屬性進行運算,將改變原有變量所指向對象的屬性值。

    上面總結出來的不過是我們所看到的表面現象。那么,為什么會出現這樣的現象呢?這就要說到值傳遞和引用傳遞的概念了。這個問題向來是頗有爭議的。

    大家都知道,在JAVA中變量有以下兩種:
    1. 基本類型變量,包括char、byte、short、int、long、float、double、boolean。
    2. 引用類型變量,包括類、接口、數組(基本類型數組和對象數組)。

    當基本類型的變量被當作參數傳遞給方法時,JAVA虛擬機所做的工作是把這個值拷貝了一份,然后把拷貝后的值傳遞到了方法的內部。因此在上面的例子中,我們回頭來看看這個方法:
    Java代碼 復制代碼
    1. // 為方法參數重新賦值   
    2. public void change(int i) {   
    3.      i = 5;   
    4. }  

    在這個方法被調用時,變量i和ParamTest型對象t的屬性num具有相同的值,卻是兩個不同變量。變量i是由JAVA虛擬機創建的作用域在 change(int i)方法內的局部變量,在這個方法執行完畢后,它的生命周期就結束了。在JAVA虛擬機中,它們是以類似如下的方式存儲的:

    很明顯,在基本類型被作為參數傳遞給方式時,是值傳遞,在整個過程中根本沒有牽扯到引用這個概念。這也是大家所公認的。對于布爾型變量當然也是如此,請看下面的例子:
    Java代碼 復制代碼
    1. public class BooleanTest {   
    2.     // 布爾型值   
    3.     boolean bool = true;   
    4.   
    5.     // 為布爾型參數重新賦值   
    6.     public void change(boolean b) {   
    7.          b = false;   
    8.      }   
    9.   
    10.     // 對布爾型參數進行運算   
    11.     public void calculate(boolean b) {   
    12.          b = b && false;   
    13.         // 為了方便對比,將運算結果輸出   
    14.          System.out.println("b運算后的值:" + b);   
    15.      }   
    16.   
    17.     public static void main(String[] args) {   
    18.          BooleanTest t = new BooleanTest();   
    19.   
    20.          System.out.println("參數--布爾型");   
    21.          System.out.println("原有的值:" + t.bool);   
    22.         // 為布爾型參數重新賦值   
    23.          t.change(t.bool);   
    24.          System.out.println("賦值之后:" + t.bool);   
    25.   
    26.         // 改變布爾型參數的值   
    27.          t.calculate(t.bool);   
    28.          System.out.println("運算之后:" + t.bool);   
    29.      }   
    30. }  

    輸出結果如下:
    1. 參數--布爾型
    2. 原有的值:true
    3. 賦值之后:true
    4. b運算后的值:false
    5. 運算之后:true

    那么當引用型變量被當作參數傳遞給方法時JAVA虛擬機又是怎樣處理的呢?同樣,它會拷貝一份這個變量所持有的引用,然后把它傳遞給JAVA虛擬機為方法 創建的局部變量,從而這兩個變量指向了同一個對象。在篇首所舉的示例中,ParamTest類型變量t和局部變量pt在JAVA虛擬機中是以如下的方式存 儲的:

    有一種說法是當一個對象或引用類型變量被當作參數傳遞時,也是值傳遞,這個值就是對象的引用,因此JAVA中只有值傳遞,沒有引用傳遞。還有一種說法是引 用可以看作是對象的別名,當對象被當作參數傳遞給方法時,傳遞的是對象的引用,因此是引用傳遞。這兩種觀點各有支持者,但是前一種觀點被絕大多數人所接 受,其中有《Core Java》一書的作者,以及JAVA的創造者James Gosling,而《Thinking in Java》一書的作者Bruce Eckel則站在了中立的立場上。

    我個人認為值傳遞中的值指的是基本類型的數值,即使對于布爾型,雖然它的表現形式為true和false,但是在棧中,它仍然是以數值形式保存的,即0表 示false,其它數值表示true。而引用是我們用來操作對象的工具,它包含了對象在堆中保存地址的信息。即使在被作為參數傳遞給方法時,實際上傳遞的 是它的拷貝,但那仍是引用。因此,用引用傳遞來區別與值傳遞,概念上更加清晰。

    最后我們得出如下的結論:
    1. 基本類型和基本類型變量被當作參數傳遞給方法時,是值傳遞。在方法實體中,無法給原變量重新賦值,也無法改變它的值。
    2. 對象和引用型變量被當作參數傳遞給方法時,在方法實體中,無法給原變量重新賦值,但是可以改變它所指向對象的屬性。至于到底它是值傳遞還是引用傳遞,這并不重要,重要的是我們要清楚當一個引用被作為參數傳遞給一個方法時,在這個方法體內會發生什么。

    什么叫引用?只因為這個變量的值和其它的不一樣.


    首先理解:都是變量
    int i;
    ArrayList b;
    i和b都是變量.
    但i是基本變量,也叫原始變量.
    其它的就叫引用變量,因為它的值是一個內存地址值.引用對象的.但記住:它們都是有一個值的!i是一個數字,而b是一個內存地址值(簡單的說是一個十六進 制的值).除了基本變量之外的變量都是引用變量.Vector a;這里的a也是一個變量.它也是有值的,它的值是一個十六進制的值.

    變量的賦值:
    int i=10;
    int j=i;
    //這里把i的值10給了j,所以j的值也是10

    ArrayList b=new ArrayList();
    ArrayList c=b;
    //首先,b是一個引用變量,它的"值":是一個內存地址值!!! new ArrayList()要分配一段內存保存它們,怎么樣找到這段內存?那就是通過b里的值了.b的值就是new ArrayList()所占內存的首地址.然后c也是一個引用變量,它的值(地址值)和b是一樣的.也就是new ArrayList()所占內存的首地址.所以當通過b或者c進行操作時,它們都是操作同一個對象的.

    在方法調用的時候,方法的參數實際也就是一個變量.如果是基本類型變量的時候,假設有方法method(int aa);
    int j=10;
    method(j);
    這里邊,int aa實際也是定義了一個變量,調用的時候把j的值:10也給了aa.所以aa也是10,改變了aa的值并不會改變j的值.

    如果是引用變量的時候,假設有方法methodA(ArrayList aa);
    ArrayList b = new ArrayList();
    methodA(b);
    //方法定義了變量aa,調用的時候把b的值(地址值!!!!!)給了aa,所以aa與b有一樣的值(地址值!!!!),在方法里通過aa去操作的時候,b所引用的對象也就被改變了,因為它們引用同一個對象.

    紙 a = new 銀行帳戶();//開一個銀行帳戶,返回一個卡號給你,寫在你的紙a里邊.

    用一張紙(引用變量),把你的銀行卡號寫在上邊,然后調用我的時候,我用另外一張紙(引用變量---方法的形數),把你的號碼抄過來.然后我通過這個卡號,去到銀行找到你的帳號,給你存點錢.

    然后你用你的紙(引用變量)上的卡號 <沒變,還是那個卡號>再去查詢銀行帳號的時候就會發現了多了一些錢了.....

    說說我對值傳遞和引用傳遞的看法:
    首先我認為,大家對Java傳遞參數的行為是清楚的,這個爭論只是一個語義上的爭論。
    也就是我們是否需要區分值傳遞和應用傳遞呢?或者說這樣的區分有沒有意義?是否合理?

    博主認為存在引用傳遞的關鍵點在于,傳遞的對象地址值,本質上它是一個引用,無論它是否被copy過。
    認為只有值傳遞的關鍵點在于,傳遞的對象地址值,它是一個值的copy,這個值代表的意義無所謂。

    引用是c++里的概念,由于java跟c++是有一定關系的,這里把引用遷移過來,如果合理未嘗不可。
    c++中關于引用的解釋一般喜歡說是看作“別名”,我查了幾本書,大部分提到引用并不會分配內存空間,也有一本書提到,某些編譯器會分配存儲空間來存儲被引用對象的地址。
    那么還是回到語義上來,c++里的這個引用,語義上是“別名”的意思,我的理解是,一組指向同一個對象的別名應該只存儲一份內存地址。當然具體實現可能會 把引用當做一個不可變的指針來處理(每個別名都存儲自己的對象地址)。但是請注意,我們應該關注于它的語義,即:它沒有任何值的copy,即使是一個地 址,只是另外一個名字而已。

    但是java里面沒有這樣的概念,所有的地址傳遞其行為是值的傳遞方式,語義上統一成值傳遞更為清晰,我們只需要考慮這個值具體是什么,無非兩種,要么是基本類型值,要么是個地址。
    所以我認為這個“引用”的概念放到java中并不合適。只有值傳遞的說法更合理。

    posted @ 2008-09-12 10:25 保爾任 閱讀(3423) | 評論 (1)編輯 收藏
    Linux 發展到今天,可用的軟件已經非常多了。這樣自然會有一些軟件的功能大致上相同。例如,同樣是編輯器,就有 nvi、vim、emacs、nano,而且我說的這些還只是一部分。大多數情況下,這樣的功能相似的軟件都是同時安裝在系統里的,可以用它們的名稱來執 行。例如,要執行 vim,只要在終端下輸入 vim 并按回車就可以了。不過,有些情況下我們需要用一個相對固定的命令調用這些程序中的一個。例如,當我們寫一個腳本程序時,只要寫下 editor,而不希望要為“編輯器是哪個”而操心。Debian 提供了一種機制來解決這個問題,而 update-alternatives 就是用來實現這種機制的。

    在說明 update-alternatives 的詳細內容之間,先讓我們看看系統中已有的例子。打開終端,執行下面的命令:

    herbert@natsu:~$ ls -l /usr/bin/editor
    lrwxrwxrwx 1 root root 24 2004-09-26 08:48 /usr/bin/editor -> /etc/alternatives/editor
    herbert@natsu:~$ ls -l /etc/alternatives/editor
    lrwxrwxrwx 1 root root 12 2004-10-27 16:24 /etc/alternatives/editor -> /usr/bin/vim
    herbert@natsu:~$

    我 們看到,editor 這個可執行命令實際上是個符號鏈接,它指向 /etc/alternatives/editor;而 /etc/alternatives/editor 也是個符號鏈接,它指向 /usr/bin/vim。這樣,當我輸入 editor 并回車時,將執行 vim。之所以要在 /usr/bin 和 /etc/alternatives 中費心建立這樣兩個鏈接,就是要實現上面說到的特性:方便腳本
    程序的編寫和系統的管理。

    下面我們就來看看 update-alternatives 的功能。當然,如果你覺得我說得不詳細,可以看看這個命令的 manpage:UPDATE-ALTERNATIVES(8)。

    首先要介紹的參數是 --display。它使我們可以看到一個命令的所有可選命令。執行

    natsu:/home/herbert# update-alternatives --display editor
    editor - status is auto.
     link currently points to /usr/bin/vim
    /bin/ed - priority -100
     slave editor.1.gz: /usr/share/man/man1/ed.1.gz
    /usr/bin/nvi - priority 19
     slave editor.1.gz: /usr/share/man/man1/nvi.1.gz
    /bin/nano - priority 40
     slave editor.1.gz: /usr/share/man/man1/nano.1.gz
    /usr/bin/vim - priority 120
     slave editor.1.gz: /usr/share/man/man1/vim.1.gz
    /usr/bin/emacs21 - priority 0
     slave editor.1.gz: /usr/share/man/man1/emacs.1emacs21.gz
    Current `best' version is /usr/bin/vim.
    natsu:/home/herbert#

    你可以看到我的機器上的所有可以用來被 editor 鏈接的命令。

    下面說說 --config。這個選項使我們可以選擇其中一個命令:

    natsu:/home/herbert# update-alternatives --config editor

    There are 5 alternatives which provide `editor'.

      Selection Alternative
    -----------------------------------------------
          1 /bin/ed
          2 /usr/bin/nvi
          3 /bin/nano
    *+    4 /usr/bin/vim
          5 /usr/bin/emacs21

    Press enter to keep the default[*], or type selection number: 4
    Using `/usr/bin/vim' to provide `editor'.
    natsu:/home/herbert#

    我并沒有修改它,因為我還是比較喜歡 vim 的。當然,你可以選擇別的程序。

    說 到這里我們就要介紹一些概念了。首先,update-alternatives 在一般情況下是由 postinst 和 prerm 這樣的安裝腳本自動調用的,所以一個 alternative 的狀態有兩種:自動和手動。每個 alternative 的初始狀態都是自動。如果系統發現管理員手動修改了一個 alternative,它的狀態就從自動變成了手動,這樣安裝腳本就不會更新它了。如果你希望將一個 alternative 變回自動,只要執行

    update-alternatives --auto editor

    就可以了。你注意到了嗎?我們說到了“名字”。該怎樣寫名字呢?這就是我們要介紹的第二個概念:
    general name -- 這是指一系列功能相似的程序的“公用”名字(包括絕對路徑),比如 /usr/bin/editor。
    link -- 這是指一個 alternative 在 /etc/alternative 中的名字,比如 editor。
    alternative -- 顧名思義,這是指一個可選的程序所在的路徑(包括絕對路徑),比如 /usr/bin/vim。
    -- auto,--display 和 --config 跟的都是 link。我們要說的第三個概念是優先級。這個比較簡單,當然優先級越高的程序越好啦(在大多數情況下,我不想爭論)最后一個概念是主和從的 alternative。想想看,你將 /usr/bin/editor 鏈接到了 vim,可是當你執行 man editor 時看到的卻是 emacs 的 manpage,你會做何感想呢?這就引出了主和從 alternative 的概念了:當更新主的 alternative 時,從的 alternative 也會被更新。

    說完這四個重要的概念后,我們介紹另外兩個選項。至于其他的。。。。我相信你會去看手冊頁的,對嗎?

    第一個是 --install。它的格式是:

    update-alternatives --install gen link alt pri [--slave sgen slink salt] ...

    gen, link,alt,pri 分別是我們上面說過的。如果需要從的 alternative,你可以用 --slave 加在后面。如果你在向一個已經存在的 alternative 組中添加新的 alternatives,該命令會把這些 alternatives 加入到這個已經存在的 alternative 組的
    列表中,并用新的可選命令作為新的命令;否則,將會建立一個新的自動的 alternative 組。

    嗚呼!我加入了一個錯誤的 alternative。我不想要這個 alternative 了。在這種情況 下,可以執行下面的命令:

    update-alternatives --remove name path

    name 是一個在 /etc/alternatives 中的名字,也就是上面的 link,而 path 是希望刪除的可選程序名的絕對路徑名(放心,這樣只是從列表中刪除了這個程序,并不會真的從硬盤上刪除程序的可執行文件)。如果從一個 alternative 組中刪除了一個正在被鏈接的程序并且這個組仍然沒有變成空的,update-alternatives 會自動用一個具有其他優先級的可選程序代替原來的程序。如果這個組變成空的了,那么連這個 alternative 組都會被移除。如果刪除的程序沒有被鏈接,則只有有關這個程序的信息會被移除。

    說個例子吧。我下載了 Eclipse,并且安裝了 gcj 和 gij。可是我發現 GNU 的 java 工具還不足以運行 Eclipse。我只好到 Sun 公司的網頁上下載了它的 java 工具 jdk。因為是自己安裝的,我將它們安裝在 /usr/local 上,以便將來重新安裝 Linux 系統時這些程序仍然可以使用。于是我要做的就是用這個 jdk 中的 java 和 javac 來代替系統原來的。執行

    natsu:/home/herbert# update-alternatives --display java
    java - status is auto.
     link currently points to /usr/local/j2sdk1.4.2_06/bin/java
    /usr/bin/gij-wrapper-3.3 - priority 33
     slave java.1.gz: /usr/share/man/man1/gij-wrapper-3.3.1.gz
    /usr/local/j2sdk1.4.2_06/bin/java - priority 100
     slave java.1.gz: /usr/local/j2sdk1.4.2_06/man/man1/java.1
    Current `best' version is /usr/local/j2sdk1.4.2_06/bin/java.
    natsu:/home/herbert# update-alternatives --display javac
    javac - status is auto.
     link currently points to /usr/local/j2sdk1.4.2_06/bin/javac
    /usr/bin/gcj-wrapper-3.3 - priority 33
     slave javah: /usr/bin/gcjh-wrapper-3.3
     slave javac.1.gz: /usr/share/man/man1/gcj-wrapper-3.3.1.gz
     slave javah.1.gz: /usr/share/man/man1/gcjh-wrapper-3.3.1.gz
    /usr/bin/gcj-wrapper-3.4 - priority 33
     slave javah: /usr/bin/gcjh-wrapper-3.4
     slave javac.1.gz: /usr/share/man/man1/gcj-wrapper-3.4.1.gz
     slave javah.1.gz: /usr/share/man/man1/gcjh-wrapper-3.4.1.gz
    /usr/local/j2sdk1.4.2_06/bin/javac - priority 100
     slave javah: /usr/local/j2sdk1.4.2_06/bin/javah
     slave javac.1.gz: /usr/local/j2sdk1.4.2_06/man/man1/javac.1
     slave javah.1.gz: /usr/local/j2sdk1.4.2_06/man/man1/javah.1
    Current `best' version is /usr/local/j2sdk1.4.2_06/bin/javac.
    natsu:/home/herbert#

    (你看到的是我更新以后的)就可以得到關于要更新哪些 alternatives 的信息。我是這么更新的:

    update-alternatives --install /usr/bin/javac javac /usr/local/j2sdk1.4.2_06/bin/javac 100 --slave /usr/bin/javah javah /usr/local/j2sdk1.4.2_06/bin/javah --slave /usr/share/man/man1/javac.1.gz javac.1.gz /usr/local/j2sdk1.4.2_06/man/man1/javac.1 --slave /usr/share/man/man1/javah.1.gz javah.1.gz /usr/local/j2sdk1.4.2_06/man/man1/javah.1
    update-alternatives --install /usr/bin/java java /usr/local/j2sdk1.4.2_06/bin/java 100 --slave /usr/share/man/man1/java.1.gz java.1.gz /usr/local/j2sdk1.4.2_06/man/man1/java.1
    posted @ 2008-02-13 10:08 保爾任 閱讀(2575) | 評論 (0)編輯 收藏
    1, insert Ubuntu 7.10 CD
    a, format disc(primary 10G ext3; extend 59G ext3; swap 1G)

    b, install(timezone shanghai; en_US; "prepare disc space" manual, or the system will partition autoly)

    c, auto restart, go on install system(remenber cut off the net line except the netwidth is large, or it will cost long time to download from far away)

    2, config
    a, sources list
    sudo vim /etc/apt/sources.list
    # add "deb http://debian.exoweb.net/debian.cn99.com/debian etch main" into it
    sudo apt-get update
    sudo apt-get upgrade

    b, vedio card driver
    在ubuntu7.10下裝nvidia 7 series顯卡并配置雙屏顯示:

    一,顯卡驅動 + 雙顯示器
    (修改X配置命令:sudo dpkg-reconfigure xserver-xorg)

    1,到nvidia網站下載7系列顯卡的最新驅動

    2,ensure that the linux-restricted-modules or linux-restricted-modules-common packages have been uninstalled. Alternatively, you can edit the /etc/default/linux-restricted-modules or /etc/default/linux-restricted-modules-common configuration file and disable the NVIDIA linux-restricted kernel modules (nvidia, nvidia_legacy) via:

    DISABLED_MODULES="nv nvidia_new"

    3,
    sudo apt-get remove --purge nvidia-glx nvidia-glx-new
    sudo rm /etc/init.d/nvidia-glx /etc/init.d/nvidia-kernel /lib/linux-restricted-modules/.nvidia_new_installed

    4,然后ctrl+alt+1進入tty1
    sudo /etc/init.d/gdm stop
    sudo sh NVIDIA-Linux-x86-100.14.23-pkg1.run
    (這時會出現錯誤提示,說少了“libc header file...libc development package”)
    sudo apt-get install sudo apt-get install build-essential xorg-dev pkg-config linux-headers-$(uname -r), libc6-dev
    sudo sh NVIDIA-Linux-x86-100.14.23-pkg1.run
    sudo /etc/init.d/gdm start

    用application -> system tools里的nvidia工具去配置雙顯示器

    c, multi-language
    System -> Administration -> Language support: install English and Chinese
    check "input method"

    d, Wen Quan Yi font
    browse http://wenq.org/, and download 文泉驛點陣宋體 and 文泉驛矢量正黑, then install them
    System -> Preference -> Appearance -> Fonts 前四項選擇:點陣宋體(WenQuanYi Bitmap Song), 第五項不改(Monospace)
    sudo fc-cache -f -v (刷新字體緩存,每次修改字體都要這樣,不然Xorg會很慢)

    e, stardict                   
    sudo apt-get install stardict
    (http://stardict.sourceforge.net/Dictionaries_zh_CN.php 下載朗道英漢,漢英字典)
    tar -xjvf *** --directory /usr/share/stardict/dic/

    f, pidgin internet messager
    sudo apt-get install gaim-guifications
    config: Tools -> Plugins -> (check) Guifications; then, config it to uncheck on "Chat message"

    3, install and config Software
    sudo apt-get install postgresql-8.1 python2.4 ipython vim-gnome sun-java5-jdk eclipse subversion build-essential ssh build-essential meld kompare

    a, postgresql
    sudo su - postgres (for user postgres has Null password, so you can't just "su - postgres", or you can sudo "sudo passwd postgres" to set password for postgres, then "su - postgres")
    createuser (enter username and password.)
    config postgresql as below:
    In /etc/postgresql/8.1/main/postgresql.conf, Change listen_addresses to '*' and change datestyle to 'ISO,European' and uncomment them.
    In /etc/postgresql/8.1/main/pg_hba.conf, 最后加入一行“host        all    justin        127.0.0.1/16        trust”

    b, eclipse
    sudo eclipse, exit, eclipse

    c, ssh
    When other mathines want to ssh or scp your mathine which is new OS, it should "rm ~/.ssh/known_hosts" to reload the new Cert.

    d, kompare
    add a file svndiff in src with context
    """
    if [ $1 ] ; then
        svn up -r $1
        svn st -q
        svn log -r $1
        PRE=`expr $1 - 1`
        svn diff --diff-cmd=diff -x "-U 10000" -r$PRE:$1 > /tmp/$1.diff
        cat /tmp/$1.diff | kompare -
    else
        svn up
        svn st
        svn diff --diff-cmd=diff -x "-U 10000" | kompare -
    fi
    """
    then, in src, ./svndiff 9827 will show diff about r9827

    e, firefox add-ons
    firebug, flashblock

    3, chroot
    a,
    sudo apt-get install debootstrap
    sudo debootstrap --arch i386 etch /home/etch http://debian.exoweb.net/debian.cn99.com/debian/
    (if in 64 bit system, use --arch amd64)
    sudo chroot /home/etch
    #in etch as root
    apt-get install locales
    dpkg-reconfigure locales #(choose en_us UTF8 as before)
    apt-get install vim vim-gnome xbase-clients less sudo postgresql-client subversion
    echo "etch" > /etc/debian-chroot
    visudo (add user justin to sudo)
    adduser justin (刪除的命令是userdel justin)

    在ubuntu的/usr/bin/etch加入:
    sudo cp /etc/passwd /home/etch/etc/
    sudo cp /etc/shadow /home/etch/etc/
    sudo cp /etc/group /home/etch/etc/
    sudo cp /etc/sudoers /home/etch/etc/
    sudo cp /etc/resolv.conf /home/etch/etc/
    sudo cp /etc/hosts /home/etch/etc/

    在/etc/fstab加入:
    /home   /home/etch/home    none    bind 0 0
    /tmp    /home/etch/tmp     none    bind 0 0
    /dev    /home/etch/dev     none    bind 0 0
    /proc   /home/etch/proc    none    bind 0 0
    sudo chroot /home/etch/  su - justin

    現在就可一享受chroot的雙系統了

    b, run X in etch 3 steps
    b1, (etch)mkdir /tmp/.X11-unix
    (ubuntu)sudo echo "/tmp/.X11-unix/x0 /home/justin/etch/tmp/.X11-unix/x0 none bind 0 0" >> /etc/fstab
    # another way is write it in to /etc/fstab, or sudo mount --bind /tmp/*** /home/justin/etch/tmp/***
    b2, (etch)vim ~/.bashrc # add "export DISPLAY=:0.0"
    b3, (ubuntu) cp ~/.Xauthority ~/etch/home/justin/ (其實這步不需要,因為上面已經把/home mount到了/home/etch/home了)

    c, install java
    #download jdk-1_5_0_14-linux-i586.bin to /opt/, and into etch/opt/
    sudo chmod +x jdk-1_5_0_14-linux-i586.bin
    sudo ./jdk-1_5_0_14-linux-i586.bin
    vim ~/.bashrc
    #add below in the end of .bashrc
    #export JAVA_HOME=/opt/jdk1.5.0_14
    #export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
    #export PATH=$JAVA_HOME/bin:$PATH

    java -version
    #java version "1.5.0_14"
    #Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_14-b03)
    #Java HotSpot(TM) Client VM (build 1.5.0_14-b03, mixed mode, sharing)
    配置默認Java使用哪個 sudo update-alternatives --config java
    posted @ 2007-12-19 17:29 保爾任 閱讀(2772) | 評論 (0)編輯 收藏
    一,兩個數的最大公約數:

    1、歐幾里德算法


    歐幾里德算法又稱輾轉相除法,用于計算兩個整數a,b的最大公約數。其計算原理依賴于下面的定理:

    定理:gcd(a,b) = gcd(b,a mod b)

    證明:a可以表示成a = kb + r,則r = a mod b
    假設d是a,b的一個公約數,則有
    d|a, d|b,而r = a - kb,因此d|r
    因此d是(b,a mod b)的公約數

    假設d 是(b,a mod b)的公約數,則
    d | b , d |r ,但是a = kb +r
    因此d也是(a,b)的公約數

    因此(a,b)和(b,a mod b)的公約數是一樣的,其最大公約數也必然相等,得證

    歐幾里德算法就是根據這個原理來做的,其算法用C++語言描述為:

    void swap(int & a, int & b){
         int c = a;
           a = b;
           b = c;
    }

    int gcd(int a,int b){
         if(0 == a ){
             return b;
         }
         if( 0 == b){
             return a;
         }
         if(a > b){
             swap(a,b);
         }
         int c;
         for(c = a % b ; c > 0 ; c = a % b){
               a = b;
               b = c;
         }
         return b;
    }

    2、Stein算法
    歐幾里德算法是計算兩個數最大公約數的傳統算法,它無論從理論還是從效率上都是很好的。但是有一個致命的缺陷,這個缺陷只有在大素數時才會顯現出來。

    考慮現在的硬件平臺,一般整數最多也就是64位,對于這樣的整數,計算兩個數之間的模是很簡單的。對于字長為32位的平臺,計算兩個不超過32位的整數的 模,只需要一個指令周期,而計算64位以下的整數模,也不過幾個周期而已。但是對于更大的素數,這樣的計算過程就不得不由用戶來設計,為了計算兩個超過 64位的整數的模,用戶也許不得不采用類似于多位數除法手算過程中的試商法,這個過程不但復雜,而且消耗了很多CPU時間。對于現代密碼算法,要求計算 128位以上的素數的情況比比皆是,設計這樣的程序迫切希望能夠拋棄除法和取模。

    Stein算法由J. Stein 1961年提出,這個方法也是計算兩個數的最大公約數。和歐幾里德算法 算法不同的是,Stein算法只有整數的移位和加減法,這對于程序設計者是一個福音。

    為了說明Stein算法的正確性,首先必須注意到以下結論:

    gcd(a,a) = a,也就是一個數和它自身的公約數是其自身
    gcd(ka,kb) = k gcd(a,b),也就是最大公約數運算和倍乘運算可以交換,特殊的,當k=2時,說明兩個偶數的最大公約數必然能被2整除

    C++/java 實現

    // c++/java stein 算法
    int gcd(int a,int b){
         if(a<b){
    //arrange so that a>b
             int temp = a;
               a = b;
               b=temp;
         }
         if(0==b)
    //the base case
            return a;
         if(a%2==0 && b%2 ==0)
    //a and b are even
             return 2*gcd(a/2,b/2);
         if ( a%2 == 0)
    // only a is even
             return gcd(a/2,b);
         if ( b%2==0 )
    // only b is even
             return gcd(a,b/2);
         return gcd((a+b)/2,(a-b)/2);
    // a and b are odd
    }

    二,多個數的最大公約數:(python實現:取出數組a中最小的,從2到最小的循環,找出其中最大的能被數組中所有數整除的那個數,就是最大公約數)
    def gcd(a):
        a.sort()
        min = a[0]
        result = 1
        for i in range(2, min+1):
            flag = True
            for j in a:
                if j % i != 0:
                    flag = False
            if flag == True:
                result = i
        return result
    posted @ 2007-12-15 15:40 保爾任 閱讀(4680) | 評論 (2)編輯 收藏
    Catalan數:(for http://acm.pku.edu.cn/JudgeOnline/problem?id=2084)

    C_n = ΣC_i*C_(n-i),其中0≤i<n;
    C_n = C(2n,n) / (n+1); 其中C(2n, n) 表示組合數,公式為:C(n, k) = n! / (k!(n-k)!)
    C_n=C_(n-1)*(4n-2)/(n+1)。

    它的意義有很多,例如:n+1邊形用對角線劃分成 三角形的方法數;n個+1和n個-1滿足所有部分和不小于零的排列數;具有n個節點的二叉樹的數量……

    (詳細說明參考:http://hi.baidu.com/kikoqiu/blog/item/81d792015ab13e01738da51d.html)
    posted @ 2007-11-16 18:07 保爾任 閱讀(1458) | 評論 (0)編輯 收藏
    指令語法

    crontab [ -u user ] file
    crontab [ -u user ] { -l | -r | -e }

    指令說明

    crontab 提供我們在固定的間隔時間執行自訂的程式、系統指令或 shell secrip。時間間隔的單位可以是分鐘、小時、日、週、月及以上的任意組合。允許使用者離線執行,並且可以將執行結果以 email 通知使用者。因此,非常設合對週期性的管理分析或資料備份等工作。

    基本上,crontab 的指令格式分為六個部分,前五個為時間間隔,最後則是執行的指令。每一個部分用空格來區隔。

    分 -- 0-59
    時 -- 0-23
    日 -- 1-31
    月 -- 1-12 或使用英文名稱
    星期 -- 0-7 或使用英文名稱
    工作命令 -- 指令,shell script,程式....(建議使用絕對路徑)
    以上是 crontab 的基本格式。

    選項說明

    -u user
    以指定的使用者身份,執行 crontab 工作。此選項僅供 root 使用。


    -l
    顯示使用者現行的 crontab 檔。

    -r
    移除現行的 crontab 檔。

    -e
    進入 vi 編輯 crontab 檔(如有設定 VISUAL 或 EDITOR 環境變數,怎使用該環境變數所設定的編輯器來編輯)。在使用者退出編輯器後,會自動將所編輯 crontab 檔,置入 crontab 執行。
    相關檔案

    /etc/cron.allow
    /etc/cron.deny

    實例說明

    # crontab -l
    # DO NOT EDIT THIS FILE - edit the master and reinstall.
    # (/tmp/crontab.3672 installed on Thu Jan 1 15:55:18 2004)
    # (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
    0 0-23/6 * * * /usr/bin/webalizer
    30 3 * * * /root/fbin/bak-web
    #

    先前曾提到,crontab 的格式分成六個部分,前五個是時間參數。在上例中你會發現除了數字與英文名稱,有使用到符號"*",這個符號代表每一單位的意思,譬如 30 3 * * * 既代表 30分 3點 每日 每月 星期的每天。

    時間的指定,可以是單一的數字,或幾個數字用逗號來連接。看下例

    30 3,12 * * * /root/fbin/bak-web

    其中的第二項為 3,12,這代表 3 以及 12 小時的意思。再來看下例

    30 */6 * * * /root/fbin/bak-web

    我把第二項改成 */6 這代表每 6 小時,也相當於 6,12,18,24 的作用。此外還有一個區段的做法

    30 8-18/2 * * * /root/fbin/bak-web

    我把第二項改成 8-18/2 這代表在 8 小時到 18 小時之間每 2 小時,也相當於 8,10,12,14,16,18 的作用。

    在認知的以上介紹各項時間用法後,你可以視實際的需要自行組合。使用上的彈性是相當自由的。這篇暫時到此。


    posted @ 2007-11-02 16:56 保爾任 閱讀(661) | 評論 (0)編輯 收藏
    (轉自:http://blog.chinaunix.net/u/24474/showart_217098.html)

    diff和patch是一對工具,在數學上來說,diff是對兩個集合的差運算,patch是對兩個集合的和運算。
    diff比較兩個文件或文件集合的差異,并記錄下來,生成一個diff文件,這也是我們常說的patch文件,即補丁文件。
    patch能將diff文件運用于 原來的兩個集合之一,從而得到另一個集合。舉個例子來說文件A和文件B,經過diff之后生成了補丁文件C,那么著個過程相當于 A -B = C ,那么patch的過程就是B+C = A 或A-C =B。
    因此我們只要能得到A, B, C三個文件中的任何兩個,就能用diff和patch這對工具生成另外一個文件。

    這就是diff和patch的妙處。下面分別介紹一下兩個工具的用法:

    1. diff的用法

    diff后面可以接兩個文件名或兩個目錄名。 如果是一個目錄名加一個文件名,那么只作用在那么個目錄下的同名文件。

    如果是兩個目錄的話,作用于該目錄下的所有文件,不遞歸。如果我們希望遞歸執行,需要使用-r參數。

    命令diff A B > C ,一般A是原始文件,B是修改后的文件,C稱為A的補丁文件。
    不加任何參數生成的diff文件格式是一種簡單的格式,這種格式只標出了不一樣的行數和內容。我們需要一種更詳細的格式,可以標識出不同之處的上下文環境,這樣更有利于提高patch命令的識別能力。這個時候可以用-c開關。


    2. patch的用法

    patch用于根據原文件和補丁文件生成目標文件。還是拿上個例子來說

    patch A C 就能得到B, 這一步叫做對A打上了B的名字為C的補丁。

    之一步之后,你的文件A就變成了文件B。如果你打完補丁之后想恢復到A怎么辦呢?

    patch -R B C 就可以重新還原到A了。

    所以不用擔心會失去A的問題。

    其實patch在具體使用的時候是不用指定原文件的,因為補丁文件中都已經記載了原文件的路徑和名稱。patch足夠聰明可以認出來。但是有時候會有點小 問題。比如一般對兩個目錄diff的時候可能已經包含了原目錄的名字,但是我們打補丁的時候會進入到目錄中再使用patch,著個時候就需要你告訴 patch命令怎么處理補丁文件中的路徑。可以利用-pn開關,告訴patch命令忽略的路徑分隔符的個數。舉例如下:

    A文件在 DIR_A下,修改后的B文件在DIR_B下,一般DIR_A和DIR_B在同一級目錄。我們為了對整個目錄下的所有文件一次性diff,我們一般會到DIR_A和DIR_B的父目錄下執行以下命令

    diff -rc DIR_A DIR_B > C

    這個時候補丁文件C中會記錄了原始文件的路徑為 DIR_A/A

    現在另一個用戶得到了A文件和C文件,其中A文件所在的目錄也是DIR_A。 一般,他會比較喜歡在DIR_A目錄下面進行patch操作,它會執行

    patch < C

    但是這個時候patch分析C文件中的記錄,認為原始文件是./DIR_A/A,但實際上是./A,此時patch會找不到原始文件。為了避免這種情況我們可以使用-p1參數如下

    patch -p1 < C

    此時,patch會忽略掉第1個”/”之前的內容,認為原始文件是 ./A,這樣就正確了。
    使用patch

    patch附帶有一個很好的幫助,其中羅列了很多選項,但是99%的時間只要兩個選項就能滿足我們的需要:

    patch -p1 < [patchfile]

    patch -R < [patchfile] (used to undo a patch)

    -p1選項代表patchfile中      文件名左邊目錄的層數,頂層目錄在不同的機器上有所不同。要使用這個選項,就要把你的patch放在要被打補丁的目錄下,然后在這個目錄中運行path -p1 < [patchfile]。
    posted @ 2007-10-25 10:22 保爾任 閱讀(1367) | 評論 (0)編輯 收藏
    斷言概述

    編寫代碼時,我們總是會做出一些假設,斷言就是用于在代碼中捕捉這些假設
    可以將斷言看作是異常處理的一種高級形式

    斷言表示為一些布爾表達式,程序員相信在程序中的某個特定點該表達式值為真

    可以在任何時候啟用和禁用斷言驗證,因此可以在測試時啟用斷言而在部署時禁用斷言。同樣,程序投入運行后,最終用戶在遇到問題時可以重新起用斷言。

    使用斷言可以創建更穩定,品質更好且易于除錯的代碼

    當需要在一個值為FALSE時中斷當前操作的話,可以使用斷言

    單元測試必須使用斷言(Junit/JunitX

    除了類型檢查和單元測試外,斷言還提供了一種確定個種特性是否在程序中得到維護的極好的方法

    使用斷言使我們向按契約式設計更近了一步



    常見的斷言特性


    前置條件斷言:代碼執行之前必須具備的特性

    后置條件斷言:代碼執行之后必須具備的特性

    前后不變斷言:代碼執行前后不能變化的特性



    斷言使用方式


    斷言可以有兩種形式

    1.assert Expression1
    2.assert Expression1:Expression2
    其中Expression1應該總是一個布爾值,Expression2是斷言失敗時輸出的失敗消息的字符串。如果Expression1為假,則拋出一個 AssertionError,這是一個錯誤,而不是一個異常,也就是說是一個不可控制異常(unchecked Exception),AssertionError由于是錯誤,所以可以不捕獲,但不推薦這樣做,因為那樣會使你的系統進入不穩定狀態。



    起用斷言


    斷言在默認情況下是關閉的,要在編譯時啟用斷言,需要使用source1.4標記javac source1.4 Test.java ,在運行時啟用斷言需要使用 -ea參數。要在系統類中啟用和禁用斷言可以使用 -esa -dsa參數。


    例如:

    public >  public AssertExampleOne(){}
      public static void main(String args[]){
        int x=10;
        System.out.println("Testing Assertion that x==100");
        assert x=100;"Out assertion failed!";
        System.out.println("Test passed!");
      }
    }

    如果編譯時未加 -source1.4,則編譯通不過

    在執行時未加 -ea 時輸出為

    Testing Assertion that x==100
    Test passed
    jre
    忽略了斷言的就代碼,而使用了該參數就會輸出為

    Testing Assertion that x==100
    Exception in thread "main" java.lang.AssertionError: Out assertion failed!
    at AssertExampleOne.main(AssertExampleOne.java:6)


    斷言的副作用


    由于程序員的問題,斷言的使用可能會帶來副作用,例如:

    boolean isEnable=false;
    //...
    assert isEnable=true;
    這個斷言的副作用是因為它修改了程序中變量的值并且未拋出錯誤,這樣的錯誤如果不細心的檢查是很難發現的。但是同時我們可以根據以上的副作用得到一個有用的特性,根據它來測試斷言是否打開。


    public >
      public static void main(String args[]){
        boolean isEnable=false;
        //...
        assert isEnable=true;
        if(isEnable==false){
          throw new RuntimeException("Assertion shoule be enable!");
        }
      }
    }


    何時需要使用斷言


    1.
    可以在預計正常情況下程序不會到達的地方放置斷言
    assert false
    2.
    斷言可以用于檢查傳遞給私有方法的參數。(對于公有方法,因為是提供給外部的接口,所以必須在方法中有相應的參數檢驗才能保證代碼的健壯性)

    3.
    使用斷言測試方法執行的前置條件和后置條件

    4.
    使用斷言檢查類的不變狀態,確保任何情況下,某個變量的狀態必須滿足。(如age屬性應大于0小于某個合適值)



    什么地方不要使用斷言


    斷言語句不是永遠會執行,可以屏蔽也可以啟用

    因此:

    1.
    不要使用斷言作為公共方法的參數檢查,公共方法的參數永遠都要執行

    2.
    斷言語句不可以有任何邊界效應,不要使用斷言語句去修改變量和改變方法的返回值

    下邊是介紹斷言的用法
    :

    assert是在J2SE1.4中引入的新特性,assertion就是在代碼中包括的布爾型狀態,程序員認為這個狀態是true。一般來說assert在開發的時候是檢查程序的安全性的,在發布的時候通常都不使用assert。在1.4中添加了assert關鍵字和java.lang.AssertError類的支持。
    首先,我們有必要從一個例子說起
    assert

    public >  public static void main(String[] args) {
        AssertTest at = new AssertTest();
        at.assertMe(true);
        at.assertMe(false);
      } 
      private void assertMe(boolean boo) {
        assert boo?true:false;
        System.out.println("true condition");
      }
    }
    程序中包含了assert的話,你要用javac -source 1.4 xxx.java來編譯,否則編譯器會報錯的。要想讓assert得部分運行的話,要使用java -ea xxx來運行,否則包含assert得行會被忽略。下面我們運行

    javac -source 1.4 AssertTest.java
    java -ea AssertTest
    看看結果的輸出是:


    true condition
    Exception in thread "main" java.lang.AssertionError
    at AssertTest.assertMe(AssertTest.java:13)
    at AssertTest.main(AssertTest.java:7)

    當我們運行at.assertMe(true)得時候,由于assert boo?true:false相當于 assert true;因此沒有任何問題,程序往下執行打印出true condition,但是執行at.assertMe(false)的時候相當于assert false,這個時候解釋器就會拋出AssertionError了,程序就終止了。大家必須清楚AssertionError是繼承自Error得,因此你可以不再程序中catch它的,當然你也可以在程序中catch它然后程序可以繼續執行。例如:

    public >  public static void main(String[] args) {
        AssertTest at = new AssertTest();
        try {
          at.assertMe(true);
          at.assertMe(false);
        } catch(AssertionError ae) {
          System.out.println("AsseriontError catched");
        }
        System.out.println("go on");
      }
      private void assertMe(boolean boo) {
        assert boo?true:false;
        System.out.println("true condition");
      }
    }

    assert
    還有另外一種表達的方式,就是assert exp1:exp2;其中exp1是個boolean返回值得表達式,而exp2可以是原始的數據類型或者對象都可以例如:

    boolean boo = true;
    String str = null;
    assert boo = false
    str="error";

    我們剛開始講得assert exp1得形式,當exp1false得時候,AssertionError得默認構造器會被調用,但是assert exp1:exp2這樣的形式,當exp1true的時候后面exp2被或略,如果false的話,后面的表達式的結果會被計算出來并作為AssertionError得構造器參數。看下面的例子:

    public >  public static void main(String[] args) {
        AssertTest at = new AssertTest();
        at.assertMe(true);
        at.assertMe(false);
      }
      private void assertMe(boolean boo) {
        String s = null;
        assert boo?true:false:s = "hello world";
        System.out.println("true condition");
      }
    }


    運行的時候會得到這樣的結果:

    true condition
    Exception in thread "main" java.lang.AssertionError: hello world
    at AssertTest.assertMe(AssertTest.java:14)
    at AssertTest.main(AssertTest.java:7)

    Assert
    最好不要濫用,原因是assert并不一定都是enable的,下面兩種情況就不應該用
    assert

    不要在public的方法里面檢查參數是不是為null之類的操作,
    例如

    public int get(String s) {
      assert s != null;
    }
    如果需要檢查也最好通過if s = null 拋出NullPointerException來檢查


    不要用
    assert來檢查方法操作的返回值來判斷方法操作的結果,
    例如

    assert list.removeAll();

    這樣看起來好像沒有問題
    但是想想如果assert disable呢,那樣他就不會被執行了所以removeAll()操作就沒有被執行可以這樣代替

    boolean boo = list.removeAl();
    assert boo;
    posted @ 2007-10-12 13:16 保爾任 閱讀(940) | 評論 (0)編輯 收藏
         摘要: Python基礎篇 整理:Jims of 肥肥世家 <jims.yang@gmail.com> Copyright © 2004,2005,2006 本文遵從GNU 的自由文檔許可證(Free Document License)的條款,歡迎轉載、修改、散布。 發布時間:2004年07月10日 更新時間:20...  閱讀全文
    posted @ 2007-09-02 16:18 保爾任 閱讀(5076) | 評論 (0)編輯 收藏
    /etc/profile:此文件為系統的每個用戶設置環境信息,當用戶第一次登錄時,該文件被執行.并從/etc/profile.d目錄的配置文件中搜集shell的設置.

    /etc/bashrc:為每一個運行bash shell的用戶執行此文件.當bash shell被打開時,該文件被讀取.

    ~/.bash_profile:每個用戶都可使用該文件輸入專用于自己使用的shell信息,當用戶登錄時,該文件僅僅執行一次!默認情況下,他設置一些環境變量,執行用戶的.bashrc文件.

    ~/.bashrc:該文件包含專用于你的bash shell的bash信息,當登錄時以及每次打開新的shell時,該該文件被讀取.

    ~/.bash_logout:當每次退出系統(退出bash shell)時,執行該文件.

    另外,/etc/profile中設定的變量(全局)的可以作用于任何用戶,而~/.bashrc等中設定的變量(局部)只能繼承/etc/profile中的變量,他們是"父子"關系.

    ~/.bash_profile 是交互式、login 方式進入 bash 運行的

    ~/.bashrc 是交互式 non-login 方式進入 bash 運行的

    通常二者設置大致相同,所以通常前者會調用后者。
    posted @ 2007-07-16 10:52 保爾任 閱讀(399) | 評論 (0)編輯 收藏
    僅列出標題  下一頁

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 操美女视频免费网站| 亚洲精品国产精品乱码不卞| 亚洲日韩精品无码专区加勒比☆ | 免费一看一级毛片人| 三年片在线观看免费观看大全中国| 久久精品国产亚洲综合色| 一二三四视频在线观看中文版免费| 精品久久久久久亚洲中文字幕| 亚洲国产成人片在线观看| 国产高清免费视频| 色婷婷综合缴情综免费观看| 久久久久亚洲AV无码网站| 日本成人免费在线| 免费女人高潮流视频在线观看 | 亚洲成人黄色网址| 又粗又大又猛又爽免费视频 | 人妖系列免费网站观看| 亚洲视频在线观看网址| 亚洲人成网站观看在线播放| 久久精品国产免费观看三人同眠| 特级aa**毛片免费观看| 亚洲一区二区三区精品视频| 亚洲精品午夜国产VA久久成人| 大学生一级毛片免费看| 大地资源网高清在线观看免费| 亚洲第一综合天堂另类专| 亚洲黄色网址大全| 亚洲?V乱码久久精品蜜桃 | 国产成人亚洲精品蜜芽影院| 久久夜色精品国产噜噜亚洲AV| 久久精品国产精品亚洲艾草网美妙| 免费AA片少妇人AA片直播| 精品视频在线免费观看| 在线精品自拍亚洲第一区| 2017亚洲男人天堂一| 亚洲AV电影院在线观看| 亚洲伊人成无码综合网| 国产又大又黑又粗免费视频| aⅴ免费在线观看| 一级毛片**不卡免费播| 国产午夜无码精品免费看动漫|