日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java編程思想讀書筆記-1(第2-7章)

 mythtian 2005-10-21



一.所有對(duì)象都必須由你建立
1.    存儲(chǔ)在哪里
1.    寄存器:我們?cè)?a href="http://www./Dev/index.html" target="_blank">程序中無法控制
2.    stack:存放基本類型的數(shù)據(jù)和對(duì)象的reference,但對(duì)象本身不存放在stack中,而是存放在Heap中
3.    Heap:存放用new產(chǎn)生的數(shù)據(jù)
4.    Static storage:存放在對(duì)象中用static定義的靜態(tài)成員
5.    Constant storage:存放常量
6.    NON-RAM:硬盤等永久存儲(chǔ)空間
2.    特例:基本型別
基本類型數(shù)據(jù)存放在Stack中,存放的是數(shù)據(jù)。而產(chǎn)生對(duì)象時(shí),只把對(duì)象的reference存放在stack中,用于指向某個(gè)對(duì)象,對(duì)象本身存放在Heap中。
3.    Java中的數(shù)組
當(dāng)你產(chǎn)生某個(gè)存儲(chǔ)對(duì)象的數(shù)組時(shí),真正產(chǎn)生的其實(shí)是存儲(chǔ)reference的數(shù)組。引數(shù)組建立后,其中的每一個(gè)reference都會(huì)被自動(dòng)設(shè)為null,表示“不指向任何對(duì)象”。
二.建立新的數(shù)據(jù)型別:Class
1.    數(shù)據(jù)成員和函數(shù)
1.1    基本成員的缺省值
1)    當(dāng)class的某個(gè)成員屬于基本型別時(shí),即使你沒有為它提供初值,Java仍保證它有一個(gè)缺省值。
2)    只有當(dāng)變量身份是“class內(nèi)的成員時(shí),Java才保證為該變量提供初值。
三.函數(shù)(Mehtods),引數(shù)(arguments),返回值(return values)
1.    引數(shù)列
當(dāng)引數(shù)傳遞的是對(duì)象時(shí),傳遞的是對(duì)象的reference。
四.注解用內(nèi)嵌式文檔
Java提供兩種注解風(fēng)格:/*XXXX*/、//XXXX

第3章    控制程序流程


一.使用Java運(yùn)算符
1.關(guān)系運(yùn)算符
1.) 當(dāng)對(duì)兩個(gè)對(duì)象運(yùn)用關(guān)系運(yùn)算符進(jìn)行比較時(shí),比較的是object reference,如:
  1. java/lang/Integer.java.html" target="_blank">Integer n1 = new java/lang/Integer.java.html" target="_blank">Integer(3);
  2. java/lang/Integer.java.html" target="_blank">Integer n2 = new java/lang/Integer.java.html" target="_blank">Integer(3);
  3. java/lang/System.java.html" target="_blank">System.out.println(n1==n2);

結(jié)果為false,因?yàn)閮蓚€(gè)object reference(n1和n2)值是不同的
2) quals()的缺省行為也是拿referenct來比較。不過Java中的class覆寫了equals方法,如:
  1. java/lang/Integer.java.html" target="_blank">Integer n1 = new java/lang/Integer.java.html" target="_blank">Integer(3);
  2. java/lang/Integer.java.html" target="_blank">Integer n2 = new java/lang/Integer.java.html" target="_blank">Integer(3);
  3. java/lang/System.java.html" target="_blank">System.out.println(n1.quals(n2));//值為true

2.    邏輯運(yùn)算符
1)    只能將and、or、not施用于boolean值身上。如果邏輯運(yùn)算符兩邊的值存在non-boolean值,將會(huì)出錯(cuò),如:
  1. int test1 = 1;
  2. java/lang/System.java.html" target="_blank">System.out.println((test && 1<2);//編輯出錯(cuò),test是non-boolean值
3.    位移運(yùn)算符
如果所操作的位移對(duì)象是char、byte、short,位移動(dòng)作發(fā)生之前,其值會(huì)先被晉升為int,運(yùn)算結(jié)果會(huì)是int。
二.流程控制
1.    迭代(iteration)
1.1    逗號(hào)運(yùn)算符
逗號(hào)運(yùn)算符只能用于for循環(huán)的控制表達(dá)式中的initialization和step兩部分中,如:for(int i=0, j=I+1; I<5; i++, j=I*2)
1.2    break和continue
break表示退出循環(huán);continue表示退出本次循環(huán),回來循環(huán)起始位置。
1.3    label
label只有放在迭代語句之前才起作用,在label和迭代語句之間插入任何語句都不會(huì)起作用。
2.    Switch
switch中的選擇器必須是int或char型,如:
  1. float i = 2;
  2. switch ( i )//將出錯(cuò),因?yàn)閕不是int或char之一

3.    計(jì)算細(xì)節(jié)
1)    從float或double轉(zhuǎn)為整數(shù)值,總是以完全舍棄小數(shù)的方式進(jìn)行。
4.    Math.random()的輸出范圍是[0, 1]。

第4章    初始化和清理


一.以構(gòu)造函數(shù)(constructor)確保初始化的進(jìn)行
如果某個(gè)class具備構(gòu)造函數(shù),Java便會(huì)在對(duì)象生成之際,使用者有能力加以操作之前,自動(dòng)調(diào)用其構(gòu)造函數(shù),于是便能名確保初始化動(dòng)作一定被執(zhí)行。
二.函數(shù)重載(Method overloading)
1.    區(qū)分重載函數(shù)
由于只能從函數(shù)名和函數(shù)的引數(shù)列來區(qū)分兩個(gè)函數(shù),而重載函數(shù)具有相同的函數(shù)名稱,所以每個(gè)重載函數(shù)都必須具備獨(dú)一無二的引數(shù)列。
2.    Default構(gòu)造函數(shù)
1)    default構(gòu)造函數(shù)是一種不帶任何引數(shù)的構(gòu)造函數(shù)。如果你所開發(fā)的class不具任何構(gòu)造函數(shù),編譯器會(huì)自動(dòng)為你生成一個(gè)default構(gòu)造函數(shù)。
2)    如果你自行定義了任何一個(gè)構(gòu)造函數(shù)(不論有無引數(shù)),編譯器就不會(huì)為你生成default構(gòu)造函數(shù)。
3)    如果定義了一個(gè)class,如
  1. class Bush{
  2.   Bush(int I){}
  3. }

當(dāng)想用new Bush();來產(chǎn)生class的實(shí)例時(shí),會(huì)產(chǎn)生錯(cuò)誤。因?yàn)樵诙xclass時(shí)已定義了構(gòu)造函數(shù),所以編譯器就不會(huì)為class生成default構(gòu)造函數(shù)。當(dāng)我們用new Bush()來產(chǎn)生實(shí)例時(shí),會(huì)嘗試調(diào)用default構(gòu)造函數(shù),但在class中沒有default構(gòu)造函數(shù),所以會(huì)出錯(cuò)。如:
  1. class Sundae
  2. {
  3.     Sundae(int i) {}
  4. }
  5. public class IceCream
  6. {
  7.     public static void main(java/lang/String.java.html" target="_blank">String[] args)
  8. {
  9.             //Sundae x = new Sundae();會(huì)編譯出錯(cuò),無構(gòu)造函數(shù)Sundae()
  10.         Sundae y = new Sundae(1);
  11.     }
  12. }

*:在定義一個(gè)class時(shí),如果定義了自己的構(gòu)造函數(shù),最好同時(shí)定義一個(gè)default構(gòu)造函數(shù)
3.    關(guān)鍵字this
1)    this僅用于函數(shù)之內(nèi),能取得“喚起此一函數(shù)“的那個(gè)object reference。
2)    在構(gòu)造函數(shù)中,通過this可以調(diào)用同一class中別的構(gòu)造函數(shù),如
  1. public class Flower{
  2.         Flower (int petals){}
  3.         Flower(java/lang/String.java.html" target="_blank">String ss){}
  4.         Flower(int petals, Sting ss){
  5.         //petals++;調(diào)用另一個(gè)構(gòu)造函數(shù)的語句必須在最起始的位置
  6. this(petals);
  7.         //this(ss);會(huì)產(chǎn)生錯(cuò)誤,因?yàn)樵谝粋€(gè)構(gòu)造函數(shù)中只能調(diào)用一個(gè)構(gòu)造函數(shù)
  8.         }
  9. }

**:1)在構(gòu)造調(diào)用另一個(gè)構(gòu)造函數(shù),調(diào)用動(dòng)作必須置于最起始的位置
        2)不能在構(gòu)造函數(shù)以外的任何函數(shù)內(nèi)調(diào)用構(gòu)造函數(shù)
        3)在一個(gè)構(gòu)造函數(shù)內(nèi)只能調(diào)用一個(gè)構(gòu)造函數(shù)
4.    Static的意義
無法在static函數(shù)中調(diào)用non-static函數(shù)(反向可行)。為什么不能呢,我們看下面的例子。
例4.2.4.1
假設(shè)能在static函數(shù)中調(diào)用non-static函數(shù),那么(a)處就將出錯(cuò)。因?yàn)樵跊]有產(chǎn)生Movie class實(shí)例之前,在就不存在Movie class內(nèi)的name實(shí)例,而在getName()中卻要使用name實(shí)例,顯然的錯(cuò)誤的。
  1. class Movie{
  2.     java/lang/String.java.html" target="_blank">String name = “”;
  3.     Movie(){}
  4.     public Movie(java/lang/String.java.html" target="_blank">String name) { this.name = name; }
  5.     public static java/lang/String.java.html" target="_blank">String getName() { return name; }
  6. }
  7. public class Test{
  8.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  9.         //下面兩名先產(chǎn)生實(shí)例后再調(diào)用getName()沒有問題
  10.         //Movie movie1 = new Movie(“movie1”);
  11.         //String name1 = movie1.getName();
  12.         //下面一名將出錯(cuò)
  13.         //String name2 = Movie.getname(); (a)
  14.     }
  15. }

三.清理(cleanup):終結(jié)(finalization)與垃圾回收(garbage collection)
1)你的對(duì)象可能不會(huì)被回收
只有當(dāng)程序不夠內(nèi)存時(shí),垃圾回收器才會(huì)啟動(dòng)去回收不再被使用的對(duì)象的內(nèi)存空間。某個(gè)對(duì)象所占用的空間可能永遠(yuǎn)不會(huì)被釋放掉,因?yàn)槟愕?a href="http://www./Dev/index.html" target="_blank">程序可能永遠(yuǎn)不會(huì)逼近內(nèi)存用完的那一刻,而垃圾回收器完全沒有被啟動(dòng)以釋放你的對(duì)象所占據(jù)的內(nèi)存,那些空間便會(huì)在程序終止時(shí)才一次歸還給操作系統(tǒng)
3)    只有在采用原生函數(shù)(native methods)時(shí),才使用finalize()。
四.成員初始化(member initialization)
1)    函數(shù)中的變量不會(huì)被自動(dòng)初始化,如
  1. void f(){
  2.         int i;
  3.         i++;
  4. }

將發(fā)生編譯錯(cuò)誤,因?yàn)閕沒有被初始化。
2)    class的數(shù)據(jù)成員會(huì)被自動(dòng)初始化,具體情況如下(見P220例子):
基本型別:boolean:false、char:null(\u0000)、byte:0、short:0、int:0、
long:0 、float:0、double:0
            對(duì)象(reference):null
1.    初始化次序
1)    所有變量一定會(huì)在任何一個(gè)函數(shù)(甚至是構(gòu)造函數(shù))被調(diào)用之前完成初始化(見P233例子)
2)    在產(chǎn)生一個(gè)class的對(duì)象(包含static成員的class的代碼被裝載)時(shí),首先自動(dòng)初始化class中的static成員變量,再執(zhí)行所有出現(xiàn)于static數(shù)據(jù)定義處的初始化動(dòng)作,最后執(zhí)行static block,所有這些初始化操作只在第一次生成該對(duì)象時(shí)進(jìn)行。
3)    自動(dòng)初始化class中的其它成員變量。
4)    執(zhí)行所有出現(xiàn)于數(shù)據(jù)定義處的初始化動(dòng)作。如:int i=1;的執(zhí)行順序是先把I自動(dòng)初始化為0,再執(zhí)行數(shù)據(jù)定義處的初始化動(dòng)作,初始化為1。
5)    執(zhí)行non-static block
6)    調(diào)用構(gòu)造函數(shù)。
例:
  1. class Cup{
  2.     Cup(int marker){
  3.         java/lang/System.java.html" target="_blank">System.out.println("Cup(" + marker + ")");
  4.     }
  5.     void f(int marker){
  6.         java/lang/System.java.html" target="_blank">System.out.println("f(" + marker + ")");    
  7.     }    
  8. }
  9. class Cups{
  10.     static Cup c1 = new Cup(11);
  11.     static Cup c2;
  12.     Cup c3 = new Cup(33); 
  13.     Cup c4;
  14.     {
  15.         c3 = new Cup(3);
  16.         c4 = new Cup(4);
  17.     }
  18.     static{
  19.         c1 = new Cup(1);
  20.         c2 = new Cup(2);
  21.     }
  22.     Cups(){
  23.         java/lang/System.java.html" target="_blank">System.out.println("Cups()");
  24.     }
  25. }
  26. public class ExplicitStatic{
  27.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  28.         java/lang/System.java.html" target="_blank">System.out.println("Inside main()");
  29.         Cups.c1.f(99);
  30.     }
  31.     static Cups x = new Cups();
  32.     static Cups y = new Cups();
  33. }

結(jié)果為:
Cup(11)
Cup(1)
Cup(2)
Cup(33)
Cup(3)
Cup(4)
Cups()
Cup(33)
Cup(3)
Cup(4)
Cups()
Inside main()
f(99)
2.    Array的初始化
1)    定義數(shù)組時(shí)不能指定大小。如int[4] iArr = {0, 1, 2, 3};,由于指定了數(shù)組的大小,會(huì)編譯出錯(cuò)。
2)    數(shù)組只是存放reference的數(shù)組。Array與non-array的結(jié)構(gòu)圖如下:
a)對(duì)于基本型別數(shù)據(jù),存放的是數(shù)據(jù)。如
int i = 5;
 
b)對(duì)于class變量,存放的是reference,這個(gè)reference指向一個(gè)存有class實(shí)例的內(nèi)存空間。如
  1. java/lang/String.java.html" target="_blank">String s = “hello”;

 
變量s存放的是一個(gè)reference,這個(gè)reference指向一個(gè)存有String實(shí)例的內(nèi)存空間。
c)對(duì)于基本型別數(shù)組,存放的是reference數(shù)組,數(shù)組中的每一個(gè)reference都指向一個(gè)class實(shí)例的內(nèi)存空間。如
  1. int[] ia = {10, 11, 12};

 
數(shù)組ia存放的是一個(gè)reference數(shù)組,數(shù)組中的每一個(gè)reference都指向一個(gè)的int實(shí)例的內(nèi)存空間。
d)對(duì)于class數(shù)組,存放的是reference數(shù)組,數(shù)組中的每一個(gè)reference都指向一個(gè)的class實(shí)例的內(nèi)存空間。如
  1. java/lang/String.java.html" target="_blank">String[] sa = {“hello1”, “hello2”, “hello3”}; 
 
 
數(shù)組sa存放的是一個(gè)reference數(shù)組,數(shù)組中的每一個(gè)reference都指向一個(gè)的String實(shí)例的內(nèi)存空間。
3)    任何數(shù)組都要進(jìn)行初始化,使用沒有進(jìn)行初始化的數(shù)組會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤,如: 
  1. int[] iArr;
  2. java/lang/System.java.html" target="_blank">System.out.pritnln(iArr[0]);//產(chǎn)生錯(cuò)誤,因?yàn)閕Arr還未初始化

數(shù)組初始化可在任何地方,可用以下方法來對(duì)數(shù)組進(jìn)行初始化:
a)    int[] iArr = {1,1,1,1};//數(shù)組的長度為{}元素的個(gè)數(shù)
b)    int i = 10; 
  1. int[] iArr = new int[i];//數(shù)組的長度可為變量(這在C/C++中不行)
  2. java/lang/System.java.html" target="_blank">System.out.println(iArr[0]);//iArr[0]是一個(gè)int,自動(dòng)初始化值為0
  3. java/lang/Integer.java.html" target="_blank">Integer[] iArr2 = new java/lang/Integer.java.html" target="_blank">Integer[i];
  4. java/lang/System.java.html" target="_blank">System.out.println(iArr2[0]);//iArr[0]是一個(gè)reference,自動(dòng)初始為null


I)    對(duì)于基本型別數(shù)組,new產(chǎn)生的是用于存放數(shù)據(jù)的數(shù)組;否則,產(chǎn)生的只是存放reference的數(shù)組。
II)    new可用來初始化基本型別的數(shù)組,但不能產(chǎn)生non-array的  基本型別數(shù)據(jù)。
c)    int[] iArr = new int[]{1,1,1,1};
  1. java/lang/Integer.java.html" target="_blank">Integer[] iArr2 = new java/lang/Integer.java.html" target="_blank">Integer[]{new java/lang/Integer.java.html" target="_blank">Integer(1), new java/lang/Integer.java.html" target="_blank">Integer(2)};

3.    多維數(shù)組(Multidimensional)arrays
多維數(shù)組每一維的大小可以不一樣,如:
  1. java/lang/Integer.java.html" target="_blank">Integer[][][] a5;
  2. a5 = new java/lang/Integer.java.html" target="_blank">Integer[3];
  3. for(int i=0; i<a5.length; i++)
  4.    a5[i] = new java/lang/Integer.java.html" target="_blank">Integer[i+1];
  5.    for(int j=0; j<a5[i].length
  6.        a5[i][j] = new java/lang/Integer.java.html" target="_blank">Integer[i+j+1];

第5章    隱藏實(shí)現(xiàn)細(xì)節(jié)


一.Java訪問權(quán)限飾詞(access specifiers)
Java有public、protect、friendly、private四種訪問權(quán)限,并且這四訪問權(quán)限的訪問范圍越來越小。
1.    friendly
1)    果一個(gè)class內(nèi)的數(shù)據(jù)成員或方法沒有任何權(quán)限飾詞,那么它的缺省訪問權(quán)限就是friendly。同一個(gè)package內(nèi)的其它所有classes都可以訪問friendly成員,但對(duì)package以外的classes則形同private。
2)  對(duì)于同一個(gè)文件夾下的、沒有用package的classes,Java會(huì)自動(dòng)將這些classes初見為隸屬于該目錄的default package,可以相互調(diào)用class中的friendly成員。如以下兩個(gè)class分別在同一個(gè)文件夾的兩個(gè)文件中,雖然沒有引入package,但隸屬于相同的default package。
  1. class Sundae{
  2.         //以下兩個(gè)方法缺省為friendly
  3.             Sundae(){}
  4.         java/lang/Void.java.html" target="_blank">Void f() {java/lang/System.java.html" target="_blank">System.out.println(“Sundae.f()”);
  5. }
  6. public class IceCream{
  7.             public static void main(java/lang/String.java.html" target="_blank">String[] args){
  8.             Sundae x = new Sundae();   
  9.             x.f();
  10.             }
  11. }

2.    public:可以被任何class調(diào)用
3.    private:private成員只能在成員所屬的class內(nèi)被調(diào)用,如:
  1. class Sundae{
  2.     private Sundae(){}//只能在Sundae class中被調(diào)用
  3.     Sundae(int i) {}
  4.     static Sundae makASundae()    {
  5.         return new Sundae();
  6.     }
  7. }
  8. public class IceCream{
  9.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  10.         // Sundae class中構(gòu)造函數(shù)Sundae()是private,
  11.         // 所以不能用它進(jìn)行初始化
  12.         //Sundae x = new Sundae();
  13.         Sundae y = new Sundae(1);//Sundae(int)是friendly,可以在此調(diào)用
  14.         Sundae z = Sundae.makASundae();
  15.     }
  16. }

4.    protected:具有friendly訪問權(quán)限的同時(shí),又能被subclass(當(dāng)然包括子孫類,即子類的子類)所訪問。即,既能被同一package中的classes訪問,又能被protected成員所在class的subclass訪問。

二.Class的訪問權(quán)限
    1.Class同樣具有public、protect、friendly、private四種訪問訪問權(quán)限:
        1)public:在任何地方都可被使用
2)protect、private:除了它自己,沒有任何class可以使用,所以class不能是
protected或private(inner class除外)
3)    friendly:同一個(gè)package中的classes能用
2.    如何調(diào)用構(gòu)造函數(shù)被聲明為private的class
1)    用static函數(shù)
2)    用Singteton模式
  1. class Soup{
  2.     private Soup(){}
  3.      //(1)靜態(tài)函數(shù)方法
  4.         public static Soup makeSout(){
  5.             return new Soup();
  6.         }
  7.      //(2)The "Singleton" pattern:
  8.      private static Soup ps1 = new Soup();
  9.      public static Soup access(){
  10.          return ps1;
  11.      }
  12.      public void f(java/lang/String.java.html" target="_blank">String msg){
  13.          java/lang/System.java.html" target="_blank">System.out.println("f(" + msg + ")");
  14.      }
  15.  }
  16.  public class Lunch{
  17.      public static void main(java/lang/String.java.html" target="_blank">String[] args){
  18.          //Soup priv1 = new Soup();編譯錯(cuò)誤
  19.          Soup priv2 = Soup.makeSout();
  20.          Soup priv3 = Soup.access();
  21.          priv2.f("priv2");
  22.          priv3.f("priv3");
  23.      }


第6章    重復(fù)運(yùn)用classes


一.繼承(inheritance)
1.    在derived class中overriding某個(gè)函數(shù)時(shí),只能覆寫base class中的接口,即base class中的public或protected或friendly函數(shù)。如果試圖overriding一個(gè)private函數(shù),雖然編譯通過,但實(shí)際上你只是在derived class中添加了一個(gè)函數(shù)。如
  1. class Cleanser{    
  2.      private void prt(){//(b)
  3.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser.prt()");
  4.     }
  5.  }
  6. public class ExplicitStatic extends Cleanser{
  7.     public void prt(){
  8.         java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic.prt()");
  9.     }
  10.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  11.         Cleanser x = new ExplicitStatic();
  12.         x.prt();//(a)
  13.     }
  14. }

因?yàn)镃leanser中的prt()是private,所以不能在其derived class中被覆寫。ExplicitStatic中的prt()只是ExplicitStatic中的一個(gè)函數(shù),所以當(dāng)試圖在(a)處通過多態(tài)來調(diào)用prt()時(shí),會(huì)發(fā)生錯(cuò)誤。如果把(b)處的private去掉,則結(jié)果為
    ExplicitStatic.prt()
2.    Super的使用
1)通過關(guān)鍵字super可以調(diào)用當(dāng)前class的superclass(父類)。
例6.1.1.1
  1. class Base{
  2.     Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");}
  3.     public void scrub() { java/lang/System.java.html" target="_blank">System.out.println(" Base.scrub()"); }
  4. }
  5. class Cleanser extends Base{
  6.     private java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser");
  7.     public void append(java/lang/String.java.html" target="_blank">String a) { s+=a; }
  8.     public void dilute() { append(" dilute()"); }
  9.     public void apply() { append(" apply()"); }
  10.     public void scrub() { append(" scrub()"); }
  11.     public void print() { java/lang/System.java.html" target="_blank">System.out.println(s); }
  12.     Cleanser(){
  13.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s);
  14.     }
  15.     public static void testStatic(){
  16.         java/lang/System.java.html" target="_blank">System.out.println("testStatic()");
  17.     }
  18.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  19.         Cleanser x = new Cleanser();
  20.         x.dilute(); x.apply(); x.scrub(); x.print();
  21.     }
  22.  }
  23. public class ExplicitStatic extends Cleanser{
  24.     ExplicitStatic(){
  25.         java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic()");
  26.     }
  27.     public void scrub(){
  28.         append(" Detergen.scrub()"); 
  29.         super.testStatic();
  30.         super.scrub();//調(diào)用的是Cleanser.scrub()
  31.     }
  32.     public void foam() { append(" foam()"); }
  33.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  34.         ExplicitStatic x = new ExplicitStatic();
  35.         x.dilute(); x.apply(); x.scrub(); x.foam();
  36.         x.print(); java/lang/System.java.html" target="_blank">System.out.println("Test base class:");
  37.         Cleanser.main(args);   
  38.         testStatic();
  39.     }
  40. }

運(yùn)行結(jié)果:
Base()
Cleanser(): Cleanser
ExplicitStatic()
testStatic()
Cleanser dilute() apply() Detergen.scrub() scrub() foam()
Test base class:
Base()
Cleanser(): Cleanser
Cleanser dilute() apply() scrub()
testStatic()
2)通過super來調(diào)用superclass中的成員時(shí),調(diào)用的是最近成員。
例6.1.1.2
  1. class Base{
  2.     protected java/lang/String.java.html" target="_blank">String baseS = "Base";//(a)
  3.     //private String baseS = "Base";
  4.     Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");}
  5. }
  6. class Cleanser extends Base{
  7.     protected java/lang/String.java.html" target="_blank">String baseS = "Cleanser";//(b)
  8.     public java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser");
  9.     Cleanser(){
  10.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s);
  11.     }
  12.     Cleanser(java/lang/String.java.html" target="_blank">String a){
  13.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser(" + a + "): s = " + s );
  14.     }
  15.  }
  16. public class ExplicitStatic extends Cleanser{
  17.     java/lang/String.java.html" target="_blank">String s2 = s;
  18.     java/lang/String.java.html" target="_blank">String baseS = super.baseS; //(c)
  19.     ExplicitStatic(){
  20.         super("ExplicitStatic");
  21.         java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = " 
  22.           + baseS + "super.baseS = " + super.baseS); 
  23.         baseS = "ExplicitStatic";
  24.         java/lang/System.java.html" target="_blank">System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS);
  25.     }
  26.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  27.         ExplicitStatic x = new ExplicitStatic();
  28.     }
  29. }

結(jié)果1:
Base()
Cleanser(ExplicitStatic): s = Cleanser
ExplicitStatic():s2 = Cleanser, baseS = Cleanser,super.baseS = Cleanser
baseS = ExplicitStatic , super.baseS = Cleanser
在上面例子中,在三個(gè)class中都存在String bases實(shí)例。在ExplicitStatic中如果直接調(diào)用baseS,則實(shí)際調(diào)用的是當(dāng)前類ExplicitStatic中的baseS(即(c)處的成員);如果通過super.bases來調(diào)用baseS,則調(diào)用的是離當(dāng)前類ExplicitStatic最近的baseS成員,即Cleanser class中的baseS實(shí)例(即(b)處),產(chǎn)生的結(jié)果如結(jié)果1所示。如果把(b)處語句注釋掉,則將調(diào)用Base class中的baseS,結(jié)果如結(jié)果2所示。
結(jié)果2:
Base()
Cleanser(ExplicitStatic): s = Cleanser
ExplicitStatic():s2 = Cleanser, baseS = Base,super.baseS = Base
baseS = ExplicitStatic , super.baseS = Base
3.    Base class的初始化
2.1    當(dāng)你產(chǎn)生derived class對(duì)象時(shí),其中會(huì)包含base class子對(duì)象(subobject)。這個(gè)子對(duì)象就和你另外產(chǎn)生的base class對(duì)象一模一樣。
2.2    通過super()可調(diào)用base class的構(gòu)造函數(shù),但必須放在構(gòu)造函數(shù)的第一行,并且只能在構(gòu)造函數(shù)中運(yùn)用。
2.3    初始化順序?yàn)椋?br>1)    加載代碼(.class文件
2)    初始化class的靜態(tài)成員,初始化順序了“從里到外”,即從base class開始。
3)    在derived class的構(gòu)造函數(shù)中調(diào)用base class的構(gòu)造函數(shù)。
如果在derived class的構(gòu)造函數(shù)中沒有通過super()顯式調(diào)用調(diào)用base class的構(gòu)造函數(shù),編譯器會(huì)調(diào)用bass class的default構(gòu)造函數(shù)并自動(dòng)生成相應(yīng)的調(diào)用語句,從而產(chǎn)生一個(gè)base class實(shí)例。如果在derived class的構(gòu)造函數(shù)中通過super()顯示調(diào)用了父類的構(gòu)造函數(shù),則調(diào)用所指定的構(gòu)造函數(shù)。調(diào)用構(gòu)造函數(shù)的調(diào)用順序是“從里到外”。
4)    調(diào)用derived class的構(gòu)造函數(shù)。
**:當(dāng)base class沒有default構(gòu)造函數(shù)時(shí),必須在derived class的構(gòu)造函數(shù)中通過super顯示調(diào)用base class的構(gòu)造函數(shù)。
例:下面代碼的初始化過程為:
1)    裝載ExplicitStatic的代碼(裝載ExplicitStatic.class文件)。
2)    發(fā)現(xiàn)ExplicitStatic有關(guān)鍵字extends,裝載ExplicitStatic的base class的代碼(裝載Cleanser.class文件)。
3)    發(fā)現(xiàn)Cleanser有關(guān)鍵字extends,裝載Cleanser的base class的代碼(裝載Base.class文件)。
4)    初始化Base class中的靜態(tài)成員。
5)    初始化Cleanser class中的靜態(tài)成員。
6)    初始化ExplicitStatic class中的靜態(tài)成員。
如果把(c)處的代碼注釋掉,那么初始化工作到此就結(jié)束了。
7)    為ExplicitStatic對(duì)象分配存儲(chǔ)空間,并把存儲(chǔ)空間初始化為0。
8)    在ExplicitStatic class的構(gòu)造中調(diào)用super("ExplicitStatic")(在ExplicitStatic class的構(gòu)造函數(shù)中顯式調(diào)用父類的構(gòu)造函數(shù)),試圖產(chǎn)生一個(gè)Cleanser class實(shí)例。
9)    為Cleanser對(duì)象分配存儲(chǔ)空間,并把存儲(chǔ)空間初始化為0。
10)    由于Cleanser class又是繼承自Base class,會(huì)在Cleanser class的構(gòu)造函數(shù)中通過super()(由于沒有顯式調(diào)用父類的構(gòu)造函數(shù),所以自動(dòng)調(diào)用父類的default構(gòu)造函數(shù))調(diào)用父類的構(gòu)造函數(shù),試圖產(chǎn)生一個(gè)Cleanser class實(shí)例。
11)    產(chǎn)生一個(gè)Base class實(shí)例。先初始化成員變量,再調(diào)用構(gòu)造函數(shù)。
12)    回到Cleanser class,產(chǎn)生一個(gè)實(shí)例。首先初始化Cleanser class中的成員數(shù)據(jù),再執(zhí)行構(gòu)造函數(shù)Cleanser(String a)中的其余部分。
13)    回到ExplicitStatic class,產(chǎn)生一個(gè)實(shí)例。首先初始化ExplicitStatic class中的成員數(shù)據(jù),再執(zhí)行構(gòu)造函數(shù)ExplicitStatic ()中的其余部分(System.out.println(“ExplicitStatic()”))。
  1. class Base{
  2.     static int s1 = prt("s1 initialized.", 11);
  3.     int i1 = prt("i1 initialized.", 12);
  4.     Base(){
  5.         java/lang/System.java.html" target="_blank">System.out.println("Base()");
  6.         java/lang/System.java.html" target="_blank">System.out.println("s1 = " + s1 + " ,i1 = " + i1);
  7.         draw();//(d)
  8.     }
  9.     void draw(){
  10.         java/lang/System.java.html" target="_blank">System.out.println("base.draw:s1 = " + s1 + " ,i1 = " + i1);
  11.     }
  12.     static int prt(java/lang/String.java.html" target="_blank">String s, int num) {
  13.         java/lang/System.java.html" target="_blank">System.out.println(s);
  14.         return num;
  15.     }
  16. }
  17. class Cleanser extends Base{
  18.     static int s2 = prt("s2 initialized.", 21);
  19.     int i2 = prt("i2 initialized.", 22);
  20.     Cleanser(){
  21.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser()");
  22.         java/lang/System.java.html" target="_blank">System.out.println("s2 = " + s2 + " ,i2 = " + i2);
  23.     }
  24.     Cleanser(java/lang/String.java.html" target="_blank">String a){
  25.         //super();(b)
  26.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser(" + a + ")");
  27.         java/lang/System.java.html" target="_blank">System.out.println("s2 = " + s2 + " ,i2 = " + i2);
  28.     }
  29.     
  30.     void draw(){
  31.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser.draw:s2 = " + s2 + " ,i2 = " + i2);
  32.     }
  33.  }
  34. public class ExplicitStatic extends Cleanser{
  35.     static int s3 = prt("s3 initialized.", 31);
  36.     int i3 = prt("i3 initialized", 31);
  37.     ExplicitStatic(){
  38.         super("ExplicitStatic");//(a)
  39.         java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic()");
  40.         java/lang/System.java.html" target="_blank">System.out.println("s3 = " + s3 + " ,i3 = " + i3);
  41.     }
  42.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  43.         ExplicitStatic x = new ExplicitStatic();//(c)
  44.     }
  45. }

結(jié)果:
s1 initialized.
s2 initialized.
s3 initialized. 
//如果把(c)處的代碼注釋掉,輸出結(jié)果到此為止,不會(huì)輸出下面結(jié)果
i1 initialized. 
Base()
s1 = 11 ,i1 = 12
Cleanser.draw:s2 = 21 ,i2 = 0//(d)處結(jié)果
i2 initialized.
Cleanser(ExplicitStatic)//(a)處結(jié)果
s2 = 21 ,i2 = 22
i3 initialized
ExplicitStatic()
s3 = 31 ,i3 = 31
由于在Base()中調(diào)用draw()時(shí),Cleanser中的i2還未進(jìn)行初始化,而在為Cleanser對(duì)象分配存儲(chǔ)空間時(shí),把存儲(chǔ)空間初始化為0,所以此時(shí)i2為0。
2.4    代碼及結(jié)果中的(a)說明了是先產(chǎn)生當(dāng)前class的base class的實(shí)例,否則在derived class中無法調(diào)用base class的成員。在調(diào)用Cleanser class的構(gòu)造函數(shù)Cleanser(String a)時(shí),在Cleanser(String a)中沒有用super顯式調(diào)用Base class的構(gòu)造函數(shù),所以系統(tǒng)會(huì)自動(dòng)生成調(diào)用Base class的default構(gòu)造函數(shù)的語句,如(b)。
4.    組合與繼承之間的快擇
.    1)繼承表示的是一種“is-a(是一個(gè))”的關(guān)系,如貨車是汽車中的一種;組合表示的是一種“has-a(有一個(gè))”的關(guān)系,如汽車有四個(gè)輪子。
        2)是否需要將新的class向上轉(zhuǎn)型為base class。
5.    在繼承中的訪問權(quán)限
protect變量能被子孫類所調(diào)用。如Base class中的baseS能被Cleanser class和ExplicitStatic class調(diào)用。
  1. class Base{
  2.     protected java/lang/String.java.html" target="_blank">String baseS = "Base";
  3.     //private String baseS = "Base";
  4.     Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");}
  5. }
  6. class Cleanser extends Base{
  7.     protected java/lang/String.java.html" target="_blank">String baseS = "Cleanser";
  8.     public java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser");
  9.     Cleanser(){
  10.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s);
  11.     }
  12.     Cleanser(java/lang/String.java.html" target="_blank">String a){
  13.         java/lang/System.java.html" target="_blank">System.out.println("Cleanser(" + a + "): s = " + s );
  14.     }
  15.  }
  16. public class ExplicitStatic extends Cleanser{
  17.     java/lang/String.java.html" target="_blank">String s2 = s;
  18.     java/lang/String.java.html" target="_blank">String baseS = super.baseS;
  19.     ExplicitStatic(){
  20.         super("ExplicitStatic");
  21.         java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = " 
  22.           + baseS + "super.baseS = " + super.baseS);
  23.         baseS = "ExplicitStatic";
  24.         java/lang/System.java.html" target="_blank">System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS);
  25.     }
  26.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  27.         ExplicitStatic x = new ExplicitStatic();
  28.     }
  29. }

結(jié)果:
Base()
Cleanser(ExplicitStatic): s = Cleanser
ExplicitStatic():s2 = Cleanser, baseS = Cleanser, super.baseS = Cleanser
baseS = ExplicitStatic , super.baseS = Cleanser
二.關(guān)鍵字final
1.Final data
    1.1 final data
1)當(dāng)基本型別被定義為final,表示它的數(shù)據(jù)值不能被改變。如
            final int i = 9;
            i++;//編譯錯(cuò)誤,不能改變I的值
2) 當(dāng)object reference被定義為final時(shí),不能改變的只是reference而不是對(duì)象本身。如
  1. class Value{  
  2.     int i = 1;
  3. }
  4. public class ExplicitStatic extends Cleanser{
  5.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  6.             final Value v = new Value();//v.i = 1
  7.             v.i++;//v.i = 2
  8.             //v = new Value();
  9.     }
  10. }

由于v為final,所以不能通過new Value()使v重新指向一個(gè)對(duì)象;但是v所指向的對(duì)象的值是可以改變的(v.i++)。
1.2 blank finals
我們可以將數(shù)據(jù)成員聲明為final但不給予初值,這就是blank finals。但blank finals必須且只能在構(gòu)造函數(shù)中進(jìn)行初始化。
  1. public class ExplicitStatic {
  2.     final int ib;
  3.     final int i = 1;
  4.     ExplicitStatic()
  5.     {
  6.         ib = 2;//(a)
  7.         //i = 3;?。╞)
  8.         java/lang/System.java.html" target="_blank">System.out.println("i = " + i  + ", ib = " + ib);
  9.     }
  10.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  11.         ExplicitStatic ex = new ExplicitStatic();
  12.     }
  13. }

ib為blank finals,所以可以在構(gòu)造函數(shù)中進(jìn)行初始化。如果把(a)處的代碼注釋掉,則ib沒有初值,編譯出錯(cuò)。而i在定義處已進(jìn)行了初始化,則不能改變i的值,(b)處的代碼編譯錯(cuò)誤。
**:非blank finals成員即使在構(gòu)造函數(shù)中也不能更改其值
2.Final methods
    1)被聲明為final的函數(shù)不能被覆寫
    2)class中所有private函數(shù)自然而然會(huì)是final。
3.    Final classes
1)當(dāng)一個(gè)class被聲明為final時(shí),表示它不能被繼承,但class的數(shù)據(jù)成員不是final,可以被改變。如
  1. class SmallBrain{}
  2. final class Dinosaur{
  3.             int i = 7;
  4.             int j = i;
  5.             SmallBrain x = new SmallBrain();
  6.             void f(){};
  7. }
  8. //不能繼承final函數(shù)
  9. //class Further extends Dinosaur{}
  10. public class ExplicitStatic{
  11.             public static void main(java/lang/String.java.html" target="_blank">String[] args){
  12.                 Dinosaur n = new Dinosaur();
  13.                 n.f();
  14.                 n.i = 40;//final class中的non-final數(shù)據(jù)成員可以被改變
  15.                 n.j++;
  16.             }
  17. }

2)final class中的所有函數(shù)也都自然是final,因?yàn)闆]有人能夠加以覆寫。

第7章    多態(tài)


一.再探向上轉(zhuǎn)型(upcasting)
    將某個(gè)object reference視為一個(gè)“reference to base type“的動(dòng)作,稱為向上轉(zhuǎn)型。
1.    Upcasting后調(diào)用某個(gè)函數(shù)時(shí),如果derived class中覆寫了該函數(shù),則會(huì)調(diào)用derived class中的函數(shù);否則,會(huì)調(diào)用base class中的函數(shù)。如
  1. class First{
  2.     public void prt(){
  3.         java/lang/System.java.html" target="_blank">System.out.println("First");
  4.     }
  5. }
  6. class Second extends First{
  7.     //(a)
  8.      public void prt(){
  9.         java/lang/System.java.html" target="_blank">System.out.println("Second");
  10.     }
  11. }
  12. public class ExplicitStatic{
  13.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  14.         First n = new Second();
  15.         n.prt();;
  16.     }
  17. }

結(jié)果為Second。如果當(dāng)Second class中的prt()函數(shù)注釋掉,將輸出First。
2.    向上轉(zhuǎn)型后只能調(diào)用base class中被derived class覆寫的函數(shù)。
  1. /*
  2. abstract class First{
  3.     int i = 122;
  4.     public void prt(){
  5.         System.out.println("First.i = " + i);
  6.     }
  7.     public abstract void prt(First f);
  8. }
  9. class Second extends First{
  10.      public void prt(){
  11.         System.out.println("Second.i = " + i);
  12.     }
  13.     
  14.     public void prt(First i)
  15.     {
  16.         
  17.     }
  18.     
  19.     public void prt(int i)
  20.     {
  21.         
  22.     }
  23. }
  24. public class ExplicitStatic{
  25.     public static void main(String[] args){
  26.         First n = new Second();
  27.         n.prt(2);;
  28.     }
  29. }
  30. */
  31. class First{
  32.     public void prt(){
  33.         java/lang/System.java.html" target="_blank">System.out.println("First");
  34.     }
  35. }
  36. class Second extends First{
  37.     //(a)
  38.      public void prt(){
  39.         java/lang/System.java.html" target="_blank">System.out.println("Second");
  40.     }
  41.     public void prt(int i){//(a)
  42.         java/lang/System.java.html" target="_blank">System.out.println("Second.i = " + i);
  43.     }
  44. }
  45. public class ExplicitStatic{
  46.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  47.         First n = new Second();
  48.         n.prt(3);
  49.     }
  50. }

(a)處的函數(shù)只是Second class中的函數(shù),所以不能通過n.prt(3)進(jìn)行調(diào)用。
二.Abstract class和Abstract methods
1.    如果一個(gè)class中存在abstract class,則class也必須被聲明為abstract class。
2.    abstract class不能被實(shí)例化。
3.    如果base class是一個(gè)abstract class,那么derived class必須實(shí)現(xiàn)base class中所有的abstract methods;否則,derived class也必須被聲明為abstract class。
三.其它要點(diǎn)
1.    純粹繼承與擴(kuò)充
純粹繼承:只有base class所建議的函數(shù),才被derived class加以覆寫。
擴(kuò)充:除了覆寫base class的函數(shù),還實(shí)現(xiàn)了自己的函數(shù)
  1. abstract class First{
  2.     public abstract void f();
  3.     public abstract void g();
  4. }
  5. //純粹繼承
  6. class Second extends First{
  7.      public void f(){}
  8.      public void g(){}
  9. }
  10. //擴(kuò)充
  11. class Third extends First{
  12.      public void f(){}
  13.      public void g(){}
  14.      public void u(){}//base class不存在的函數(shù)
  15. }

2.    向下轉(zhuǎn)型
1)    向下轉(zhuǎn)型時(shí)只能調(diào)用base class中被覆寫過的函數(shù)
2)    只有本來就為derived class對(duì)象時(shí)才能正確向下轉(zhuǎn)弄。
  1. class First{
  2.      public void f(){}
  3.      public void g(){}
  4. }
  5. class Second extends First{
  6.      public void f(){}
  7.      public void g(){}
  8.      public void u(){}
  9.      public void v(){}
  10. }
  11. public class ExplicitStatic{
  12.     public static void main(java/lang/String.java.html" target="_blank">String[] args){
  13.         First[] x = {new First(), new Second()};
  14.         x[0].f();
  15.         x[1].g();
  16.         //!x[1].u();class First中不存在函數(shù)u()
  17.         //((Second)x[0]).f();(a)
  18.         ((Second)x[1]).u();
  19. }
  20. }


-------------------------------------






    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多