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

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

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

    posts - 12,  comments - 0,  trackbacks - 0
      2007年12月20日
    方法調(diào)用的綁定:
    將方法的調(diào)用連到方法本身被稱為“綁定”。當綁定發(fā)生在程序運行之前時,被稱作“前綁定”。
    后綁定也稱為“動態(tài)綁定”或“運行時綁定”,指程序運行的時候,根據(jù)對象的類型來決定該綁定哪個方法。如果語言實現(xiàn)了后綁定,那它就必須要有能在運行時判斷對象類型,并且調(diào)用其合適方法的機制。也就是說編譯器還是不知道對象的類型,但是方法的調(diào)用機制會找出,并且調(diào)用正確的方法。
    除了static和final方法(private方法隱含有final的意思),java的所有的方法都采用后綁定。也就是說,通常情況下你不必考慮是不是應該采用后綁定--它是自動的。 為什么要聲明final方法,上一章指出,這樣可以禁止別人覆寫這個方法,不過更重要的可能還是要“關(guān)閉”它的動態(tài)綁定,或者理確切的說,告訴編譯器這里不需要使用后綁定。
    shape為circle的基類,下面這句就是在“上傳”:
    Shape s = new Circle();
    這里先創(chuàng)建了一個Circle對象,接著馬上把它的引用賦給了Shape,看上去這像是一個錯誤(一種類型怎么能賦給另一種);但是由于Circle是由Shape派生出來的,Circle就是一種Shape,因此這種做法是非常正確的。假設(shè)你調(diào)用了一個基類的方法:s.draw();這里派生類里已經(jīng)覆寫了此方法,那么可能你會認為,這次應該總調(diào)用Shape的draw()了吧,因為畢竟這是Shape的引用,但是由于實現(xiàn)了后綁定(多態(tài)性),實際上它會調(diào)用Circle.draw().
    posted @ 2008-01-05 19:18 仰望者 閱讀(220) | 評論 (0)編輯 收藏
    1、 float f=1.3;
        是不對的,編譯時會出錯,java認為1.3是double型的,所以定義時應寫成:float f=1.3f,或float f= (float)1.3;
    2、 byte b = 3;  b=b*3;
        是不對的,原因是在*運算過程中,java會做類型的提升,將b提升為int型,所以應改為:b=(byte)(b*3);
    3、 while(1),if(1)
        是不對的,原因是java中布爾型只有true 和false兩個值,這里與C語言不同,只能用while(true)..
    4、 數(shù)組聲明:int num[3];
        這是不對的,java中聲明數(shù)組時不應對空間限定,正確的語法應是:
        int[] num = new int[3];
        或
        int[] num;
        num = new int[3];
    5、數(shù)組初始化:int[] num;
                   num {1,3,4,4};
       是不對的,應在定義的時候初始化。如:int[] num={1,3,4,4};
    6、int[] num3 =new int[]{1,2,3};
       int[] num5 =new int[3]{1,2,3};
       int[] num3 =new int[]{1,2,3};是對的。
        int[] num5 =new int[3]{1,2,3};是錯的。已經(jīng)初始化的數(shù)組,不應再列明:[3]
           


    posted @ 2007-12-23 23:01 仰望者 閱讀(162) | 評論 (0)編輯 收藏
    合成與繼承
    繼承:
    super關(guān)鍵字的使用:super使用在派生類中,如果派生類中重寫了基類的方法,但在這個被重寫的方法中仍然要調(diào)用基類的同名的方法,這就要用到super關(guān)鍵字,特別是在創(chuàng)建對象時,在帶參數(shù)構(gòu)造函數(shù)中調(diào)用基類構(gòu)造函數(shù)的情況。
    如:
    class Cleanser {
      private String s = new String("Cleanser");
      public void append(String a) { s += a; }
      public void dilute() { append(" dilute()"); }
      public void apply() { append(" apply()"); }
      public void scrub() { append(" scrub()"); }
      public void print() { System.out.println(s); }
      public static void main(String[] args) {
        Cleanser x = new Cleanser();
        x.dilute(); x.apply(); x.scrub();
        x.print();
      }
    }
    public class Detergent extends Cleanser {
      // Change a method:
      public void scrub() {
        append(" Detergent.scrub()");
        super.scrub(); // Call base-class version
      }
    // Add methods to the interface:
      public void foam() { append(" foam()"); }
      // Test the new class:
      public static void main(String[] args) {
        Detergent x = new Detergent();
        x.dilute();
        x.apply();
        x.scrub();
        x.foam();
        x.print();
        System.out.println("Testing base class:");
        Cleanser.main(args);
      }
    } ///:~
    可以看到基類Cleanser 中定義了scrub方法,但派生類Detergent 中對scrub方法進行了修改,并用在派生類Detergent 的scrub方法中,要調(diào)用基本的scrub方法,那么用super.scrub(); 

     基類的初始化:
             當你創(chuàng)建一個派生類的對象的時候,這個對象里面還有一個基類的子對象,這個子對象同基類自己創(chuàng)建的對象沒什么兩樣,只是從外面看來,這個子對象被包裹在派生類的對象里面。
             基類子對象的正確初始化是非常重要的,而且只有一個辦法能保證這一點:調(diào)用基類的構(gòu)造函數(shù)來進行初始化,因為只有它才能掌握怎么樣才能正確地進行初始化的信息和權(quán)限。java會讓派生類的構(gòu)造函數(shù)自動地調(diào)用基類的構(gòu)造函數(shù)。
              示例:
     class Art {
      Art() {
        System.out.println("Art constructor");
      }
    }

    class Drawing extends Art {
      Drawing() {
        System.out.println("Drawing constructor");
      }
    }

    public class Cartoon extends Drawing {
      Cartoon() {
        System.out.println("Cartoon constructor");
      }
      public static void main(String[] args) {
        Cartoon x = new Cartoon();
      }
    } ///:~
    輸出結(jié)果為:
    Art constructor
    Drawing constructor
    Cartoon constructor
    一看結(jié)果便一目了然了。

    上面的示例是不帶任何參數(shù)的情況,如果構(gòu)造函數(shù)中帶有參數(shù)的話,那這里又要用到super的特性了。與上面super的使用涵意一樣,super在這里用作:派生的帶參數(shù)構(gòu)造函數(shù)中調(diào)用基類的帶參構(gòu)造函數(shù),只是這里不象上面那樣super.scrub();這里只使用super(i);即可。
            
    class Game {
      Game(int i) {
        System.out.println("Game constructor");
      }
    }

    class BoardGame extends Game {
      BoardGame(int i) {
        super(i);
        System.out.println("BoardGame constructor");
      }
    }

    public class Chess extends BoardGame {
      Chess() {
        super(11);
        System.out.println("Chess constructor");
      }
      public static void main(String[] args) {
        Chess x = new Chess();
      }
    } ///:~
    輸出結(jié)果是:
    Game constructor
    BoardGame constructor
    Chess constructor

    合成和繼承一起使用,實現(xiàn)類的復用:

    class Plate {
      Plate(int i) {
        System.out.println("Plate constructor");
      }
    }

    class DinnerPlate extends Plate {
      DinnerPlate(int i) {
        super(i);
        System.out.println(
          "DinnerPlate constructor");
      }
    }

    class Utensil {
      Utensil(int i) {
        System.out.println("Utensil constructor");
      }
    }

    class Spoon extends Utensil {
      Spoon(int i) {
        super(i);
        System.out.println("Spoon constructor");
      }
    }

    class Fork extends Utensil {
      Fork(int i) {
        super(i);
        System.out.println("Fork constructor");
      }
    }

    class Knife extends Utensil {
      Knife(int i) {
        super(i);
        System.out.println("Knife constructor");
      }
    }

    // A cultural way of doing something:
    class Custom {
      Custom(int i) {
        System.out.println("Custom constructor");
      }
    }

    public class PlaceSetting extends Custom {
      Spoon sp;
      Fork frk;
      Knife kn;
      DinnerPlate pl;
      PlaceSetting(int i) {//把初始化工作都放在構(gòu)造函數(shù)中
        super(i + 1);
        sp = new Spoon(i + 2);
        frk = new Fork(i + 3);
        kn = new Knife(i + 4);
        pl = new DinnerPlate(i + 5);
        System.out.println(
          "PlaceSetting constructor");
      }
      public static void main(String[] args) {
        PlaceSetting x = new PlaceSetting(9);
      }
    } ///:~
            盡管編譯器會強迫我們對基礎(chǔ)類進行初始化,并要求我們在構(gòu)建器最開頭做這一工作,但它并不會監(jiān)視我們是否正確初始化了成員對象。所以對此必須特別加以留意。
    FINAL關(guān)鍵字:
            FINAL關(guān)鍵字指“那樣東西是不允許改動”,你可能會出于兩點考慮不想讓別人作改動:設(shè)計和效率。由于這兩個原因差別很大,所以很可能會誤用final關(guān)鍵字。
    final的三種用途:數(shù)據(jù)(Data)、方法(method)、類(class)。
     很多語言通知編譯器:“這段常量(constant)數(shù)據(jù)”的手段。常量能用下列兩種情況出現(xiàn):
            1、可以是“編譯時的常量”,這樣以后就不能改了;
            2、也可以是運行時初始化的值,這個值以后就不想再改了。
            如果是編譯時的常量,編譯器會把常量放到算式里面;這樣編譯的時候就能進行計算,因此也就降低了運行時的開銷。在Java 中這種常量必須是primitive 型的,而且要用final 關(guān)鍵詞表示。這種常量的賦值必須在定義的時候進行。
            一個既是static 又是final 的數(shù)據(jù)成員會只占據(jù)一段內(nèi)存,并且不可修改。
            當final 不是指primitive,而是用于對象的reference 的時候,意思就有點不一樣了。對primitive 來說,final 會將這個值定義成常量,但是對于對象的reference 而言,final 的意思則是這個reference 是常量。初始化的時候,一旦將reference 連到了某個對象,那么它就再也不能指別的對象了。但是這個對象本身是可以修改的;Java 沒有提供將某個對象作成常量的方法。
            (但是你可以自己寫一個類,這樣就能把類當做常量了)
            這種局限性也體現(xiàn)在數(shù)組上,因為它也是一個對象。
    注意,通常約定,被初始化為常量值的final static 的primitive 的名字全都用大寫,詞與詞之間用下
    劃線分開,如VAL_ONE
    Final 方法
    使用final 方法的目的有二:
            第一,為方法上“鎖”,禁止派生類進行修改。這是出于設(shè)計考慮。當你希望某個方法的功能,能在繼承過程中被保留下來,并且不被覆寫,就可以使用這個方法。
            第二個原因就是效率。如果方法是final 的,那么編譯器就會把調(diào)用轉(zhuǎn)換成“內(nèi)聯(lián)的(inline)”。它會用方法本身的拷貝來代替方法的調(diào)用
    final 和private
            private 方法都隱含有final 的意思。由于你不能訪問private 的方法,因此你也不能覆寫它。你可以給private 方法加一個final 修飾符,但是這樣做什么意義也沒有。
            這個問題有可能會造成混亂,因為即使你覆寫了一個private 方法(它隱含有final 的意思),看上去它還是可以運行的,而且編譯器也不會報錯:
            class WithFinals {
                // Identical to "private" alone:
                private final void f() {
                        System.out.println("WithFinals.f()");
                                              }
                / / Also automatically "final":
               private void g() {
                        System.out.println("WithFinals.g()");
                                     }
            }
            class OverridingPrivate extends WithFinals {
                    private final void f() {
                            System.out.println("OverridingPrivate.f()");
                                                      }
                    private void g() {
                            System.out.println("OverridingPrivate.g()");
                                                      }
             }
    只有是基類接口里的東西才能被“覆寫”,如果方法是private 的,那它就不屬于基類的接口。它只能算是被類隱藏起來的,正好有著相同的名字的代碼。如果你在派生類里創(chuàng)建了同名的public 或protected,或package 權(quán)限的方法,那么它們同基類中可能同名的方法,沒有任何聯(lián)系。你并沒有覆寫那個方法,你只是創(chuàng)建了一個新的方法。由于private 方法是無法訪問的,實際上是看不見的,因此這么作除了會影響類的代碼結(jié)構(gòu),其它什么意義都沒有。
    Final 類
    把整個類都定義成final 的(把final 關(guān)鍵詞放到類的定義部分的前面)就等于在宣布,你不會去繼承這個類,你也不允許別人去繼承這個類。換言之,出于類的設(shè)計考慮,它再也不需要作修改了,或者從安全角度出發(fā),你不希望它再生出子類。
    final class Dinosaur{}
    注意,final 類的數(shù)據(jù)可以是final 的,也可以不是final 的,這要由你來決定。無論類是不是final 的,這一條都適用于“將final 用于數(shù)據(jù)的”場合。但是,由于final 類禁止了繼承,覆寫方法已經(jīng)不可能了,因
    此所有的方法都隱含地變成final 了。你可以為final 類的方法加一個final 修飾符,但是這一樣沒什么意義。
    posted @ 2007-12-20 17:33 仰望者 閱讀(238) | 評論 (0)編輯 收藏
    訪問控制符:public 、private、protected、friendly
    public包內(nèi)包外均可訪問。
    private只有本類可訪問。
    protected針對繼承而使用的:1、包內(nèi)繼承,因為在包內(nèi),聲明為protected不影響它本來的friendly權(quán)限。
                               2、包外繼承,必須聲明為protected。
    派生類可以訪問基類的protected成員。
    注意不可將類設(shè)成private(那樣會使除類之外的其他東西都不能訪問它),也不能設(shè)成protected。因此,我們現(xiàn)在對于類的訪問只有兩個選擇:“友好的”或者public。若不愿其他任何人訪問那個類,可將所有構(gòu)建器設(shè)為private,這樣除你之外,沒有可以用類創(chuàng)建的了。而你可以使用static成員創(chuàng)建對象。
    package com.access.external;

    class Soup{
        private Soup(){//構(gòu)造函數(shù)聲明為private,其它類不能用此構(gòu)造函數(shù)創(chuàng)建對象;
            System.out.println("sffewe");
        }
        public static Soup makSoup(){//其它類可通過makSoup來創(chuàng)建對象;
            return new Soup();
        }
        private static Soup ps1 = new Soup();//自己創(chuàng)建對象;
        public static Soup access(){//返回對象的引用。
            return ps1;
        }
        public void f(){}
    }

    class Sandwich{
        void f(){
            new Lunch();
        }
    }

    public class Lunch {
        void test(){
            //Soup priv1 = new Soup();
            Soup priv2 = Soup.makSoup();
            Sandwich f1 = new Sandwich();
            Soup.access().f();//不創(chuàng)建對象,但通過Soup中返回的對象引用調(diào)用其方法。
        }

    }


    該方法返回一個句柄,它指向類Soup的一個對象。
    Soup類向我們展示出如何通過將所有構(gòu)建器都設(shè)為private,從而防止直接創(chuàng)建一個類。請記住,假若不明確地至少創(chuàng)建一個構(gòu)建器,就會自動創(chuàng)建默認構(gòu)建器(沒有自變量)。若自己編寫默認構(gòu)建器,它就不會自動創(chuàng)建。把它變成private后,就沒人能為那個類創(chuàng)建一個對象。但別人怎樣使用這個類呢?上面的例子為我們揭示出了兩個選擇。第一個選擇,我們可創(chuàng)建一個static方法,再通過它創(chuàng)建一個新的Soup,然后返回指向它的一個句柄。如果想在返回之前對Soup進行一些額外的操作,或者想了解準備創(chuàng)建多少個Soup對象(可能是為了限制它們的個數(shù)),這種方案無疑是特別有用的。
    第二個選擇是采用“設(shè)計方案”(Design Pattern)技術(shù),本書后面會對此進行詳細介紹。通常方案叫作“獨子”,因為它僅允許創(chuàng)建一個對象。類Soup的對象被創(chuàng)建成Soup的一個static private成員,所以有一個而且只能有一個。除非通過public方法access(),否則根本無法訪問它。



    posted @ 2007-12-20 11:09 仰望者 閱讀(248) | 評論 (0)編輯 收藏
    主站蜘蛛池模板: 免费少妇a级毛片| 婷婷综合缴情亚洲狠狠尤物| 亚洲午夜久久久精品电影院| jizz免费一区二区三区| 四虎影视精品永久免费| 亚洲a一级免费视频| 亚洲av无码片区一区二区三区| 国产精品区免费视频| 亚洲av无码片在线播放| 久久久国产精品福利免费| 免费看一级做a爰片久久| 亚洲精品午夜久久久伊人| 亚洲欧美第一成人网站7777 | 亚洲av色香蕉一区二区三区蜜桃| 天天摸天天操免费播放小视频| 亚洲乱码av中文一区二区| 国产jizzjizz视频免费看| 特级毛片爽www免费版| 亚洲线精品一区二区三区| 久久er国产精品免费观看2| 亚洲黄色片免费看| 91av免费在线视频| 亚洲AV无码成人精品区天堂| 57pao国产成永久免费视频| 亚洲国产成人久久笫一页 | 亚洲精品成a人在线观看夫| 久久99青青精品免费观看| 亚洲av无码国产精品色在线看不卡 | 一个人看的www免费视频在线观看| 久久亚洲精品国产精品黑人| ww4545四虎永久免费地址| 国产亚洲综合久久系列| 最近免费字幕中文大全视频| 中文无码亚洲精品字幕| 亚洲精品无码专区2| 免费A级毛片无码视频| 亚洲女女女同性video| 国产亚洲AV无码AV男人的天堂| 国产精品爱啪在线线免费观看| 91亚洲va在线天线va天堂va国产| 69成人免费视频无码专区|