一.所有對(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,如:
- java/lang/Integer.java.html" target="_blank">Integer n1 = new java/lang/Integer.java.html" target="_blank">Integer(3);
- java/lang/Integer.java.html" target="_blank">Integer n2 = new java/lang/Integer.java.html" target="_blank">Integer(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方法,如:
- java/lang/Integer.java.html" target="_blank">Integer n1 = new java/lang/Integer.java.html" target="_blank">Integer(3);
- java/lang/Integer.java.html" target="_blank">Integer n2 = new java/lang/Integer.java.html" target="_blank">Integer(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ò),如:
- int test1 = 1;
- 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型,如:
- float i = 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,如
- class Bush{
- Bush(int I){}
- }
當(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ò)。如:
- class Sundae
- {
- Sundae(int i) {}
- }
- public class IceCream
- {
- public static void main(java/lang/String.java.html" target="_blank">String[] args)
- {
- //Sundae x = new Sundae();會(huì)編譯出錯(cuò),無構(gòu)造函數(shù)Sundae()
- Sundae y = new Sundae(1);
- }
- }
*:在定義一個(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ù),如
- public class Flower{
- Flower (int petals){}
- Flower(java/lang/String.java.html" target="_blank">String ss){}
- Flower(int petals, Sting ss){
- //petals++;調(diào)用另一個(gè)構(gòu)造函數(shù)的語句必須在最起始的位置
- this(petals);
- //this(ss);會(huì)產(chǎn)生錯(cuò)誤,因?yàn)樵谝粋€(gè)構(gòu)造函數(shù)中只能調(diào)用一個(gè)構(gòu)造函數(shù)
- }
- }
**: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ò)誤的。
- class Movie{
- java/lang/String.java.html" target="_blank">String name = “”;
- Movie(){}
- public Movie(java/lang/String.java.html" target="_blank">String name) { this.name = name; }
- public static java/lang/String.java.html" target="_blank">String getName() { return name; }
- }
- public class Test{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- //下面兩名先產(chǎn)生實(shí)例后再調(diào)用getName()沒有問題
- //Movie movie1 = new Movie(“movie1”);
- //String name1 = movie1.getName();
- //下面一名將出錯(cuò)
- //String name2 = Movie.getname(); (a)
- }
- }
三.清理(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)初始化,如
將發(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ù)。 例:
- class Cup{
- Cup(int marker){
- java/lang/System.java.html" target="_blank">System.out.println("Cup(" + marker + ")");
- }
- void f(int marker){
- java/lang/System.java.html" target="_blank">System.out.println("f(" + marker + ")");
- }
- }
-
- class Cups{
- static Cup c1 = new Cup(11);
- static Cup c2;
- Cup c3 = new Cup(33);
- Cup c4;
- {
- c3 = new Cup(3);
- c4 = new Cup(4);
- }
- static{
- c1 = new Cup(1);
- c2 = new Cup(2);
- }
- Cups(){
- java/lang/System.java.html" target="_blank">System.out.println("Cups()");
- }
- }
-
- public class ExplicitStatic{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- java/lang/System.java.html" target="_blank">System.out.println("Inside main()");
- Cups.c1.f(99);
- }
- static Cups x = new Cups();
- static Cups y = new Cups();
- }
結(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)存空間。如
- 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)存空間。如
數(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)存空間。如
- 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ò)誤,如:
- int[] iArr;
- 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;
- int[] iArr = new int[i];//數(shù)組的長度可為變量(這在C/C++中不行)
- java/lang/System.java.html" target="_blank">System.out.println(iArr[0]);//iArr[0]是一個(gè)int,自動(dòng)初始化值為0
- java/lang/Integer.java.html" target="_blank">Integer[] iArr2 = new java/lang/Integer.java.html" target="_blank">Integer[i];
- 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};
- 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ù)組每一維的大小可以不一樣,如:
- java/lang/Integer.java.html" target="_blank">Integer[][][] a5;
- a5 = new java/lang/Integer.java.html" target="_blank">Integer[3];
- for(int i=0; i<a5.length; i++)
- a5[i] = new java/lang/Integer.java.html" target="_blank">Integer[i+1];
- for(int j=0; j<a5[i].length
- 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。
- class Sundae{
- //以下兩個(gè)方法缺省為friendly
- Sundae(){}
- java/lang/Void.java.html" target="_blank">Void f() {java/lang/System.java.html" target="_blank">System.out.println(“Sundae.f()”);
- }
- public class IceCream{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- Sundae x = new Sundae();
- x.f();
- }
- }
2. public:可以被任何class調(diào)用 3. private:private成員只能在成員所屬的class內(nèi)被調(diào)用,如:
- class Sundae{
- private Sundae(){}//只能在Sundae class中被調(diào)用
- Sundae(int i) {}
- static Sundae makASundae() {
- return new Sundae();
- }
- }
- public class IceCream{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- // Sundae class中構(gòu)造函數(shù)Sundae()是private,
- // 所以不能用它進(jìn)行初始化
- //Sundae x = new Sundae();
- Sundae y = new Sundae(1);//Sundae(int)是friendly,可以在此調(diào)用
- Sundae z = Sundae.makASundae();
- }
- }
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模式
- class Soup{
- private Soup(){}
- //(1)靜態(tài)函數(shù)方法
- public static Soup makeSout(){
- return new Soup();
- }
- //(2)The "Singleton" pattern:
- private static Soup ps1 = new Soup();
- public static Soup access(){
- return ps1;
- }
- public void f(java/lang/String.java.html" target="_blank">String msg){
- java/lang/System.java.html" target="_blank">System.out.println("f(" + msg + ")");
- }
- }
- public class Lunch{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- //Soup priv1 = new Soup();編譯錯(cuò)誤
- Soup priv2 = Soup.makeSout();
- Soup priv3 = Soup.access();
- priv2.f("priv2");
- priv3.f("priv3");
- }
第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ù)。如
- class Cleanser{
- private void prt(){//(b)
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser.prt()");
- }
- }
- public class ExplicitStatic extends Cleanser{
- public void prt(){
- java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic.prt()");
- }
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- Cleanser x = new ExplicitStatic();
- x.prt();//(a)
- }
- }
因?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
- class Base{
- Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");}
- public void scrub() { java/lang/System.java.html" target="_blank">System.out.println(" Base.scrub()"); }
- }
- class Cleanser extends Base{
- private java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser");
- public void append(java/lang/String.java.html" target="_blank">String a) { s+=a; }
- public void dilute() { append(" dilute()"); }
- public void apply() { append(" apply()"); }
- public void scrub() { append(" scrub()"); }
- public void print() { java/lang/System.java.html" target="_blank">System.out.println(s); }
- Cleanser(){
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s);
- }
- public static void testStatic(){
- java/lang/System.java.html" target="_blank">System.out.println("testStatic()");
- }
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- Cleanser x = new Cleanser();
- x.dilute(); x.apply(); x.scrub(); x.print();
- }
- }
- public class ExplicitStatic extends Cleanser{
- ExplicitStatic(){
- java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic()");
- }
- public void scrub(){
- append(" Detergen.scrub()");
- super.testStatic();
- super.scrub();//調(diào)用的是Cleanser.scrub()
- }
- public void foam() { append(" foam()"); }
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- ExplicitStatic x = new ExplicitStatic();
- x.dilute(); x.apply(); x.scrub(); x.foam();
- x.print(); java/lang/System.java.html" target="_blank">System.out.println("Test base class:");
- Cleanser.main(args);
- testStatic();
- }
- }
運(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
- class Base{
- protected java/lang/String.java.html" target="_blank">String baseS = "Base";//(a)
- //private String baseS = "Base";
- Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");}
- }
- class Cleanser extends Base{
- protected java/lang/String.java.html" target="_blank">String baseS = "Cleanser";//(b)
- public java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser");
- Cleanser(){
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s);
- }
- Cleanser(java/lang/String.java.html" target="_blank">String a){
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser(" + a + "): s = " + s );
- }
- }
- public class ExplicitStatic extends Cleanser{
- java/lang/String.java.html" target="_blank">String s2 = s;
- java/lang/String.java.html" target="_blank">String baseS = super.baseS; //(c)
- ExplicitStatic(){
- super("ExplicitStatic");
- java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = "
- + baseS + "super.baseS = " + super.baseS);
- baseS = "ExplicitStatic";
- java/lang/System.java.html" target="_blank">System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS);
- }
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- ExplicitStatic x = new ExplicitStatic();
- }
- }
結(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()”))。
- class Base{
- static int s1 = prt("s1 initialized.", 11);
- int i1 = prt("i1 initialized.", 12);
- Base(){
- java/lang/System.java.html" target="_blank">System.out.println("Base()");
- java/lang/System.java.html" target="_blank">System.out.println("s1 = " + s1 + " ,i1 = " + i1);
- draw();//(d)
- }
- void draw(){
- java/lang/System.java.html" target="_blank">System.out.println("base.draw:s1 = " + s1 + " ,i1 = " + i1);
- }
- static int prt(java/lang/String.java.html" target="_blank">String s, int num) {
- java/lang/System.java.html" target="_blank">System.out.println(s);
- return num;
- }
- }
- class Cleanser extends Base{
- static int s2 = prt("s2 initialized.", 21);
- int i2 = prt("i2 initialized.", 22);
- Cleanser(){
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser()");
- java/lang/System.java.html" target="_blank">System.out.println("s2 = " + s2 + " ,i2 = " + i2);
- }
- Cleanser(java/lang/String.java.html" target="_blank">String a){
- //super();(b)
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser(" + a + ")");
- java/lang/System.java.html" target="_blank">System.out.println("s2 = " + s2 + " ,i2 = " + i2);
- }
-
- void draw(){
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser.draw:s2 = " + s2 + " ,i2 = " + i2);
- }
- }
- public class ExplicitStatic extends Cleanser{
- static int s3 = prt("s3 initialized.", 31);
- int i3 = prt("i3 initialized", 31);
- ExplicitStatic(){
- super("ExplicitStatic");//(a)
- java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic()");
- java/lang/System.java.html" target="_blank">System.out.println("s3 = " + s3 + " ,i3 = " + i3);
- }
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- ExplicitStatic x = new ExplicitStatic();//(c)
- }
- }
結(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)用。
- class Base{
- protected java/lang/String.java.html" target="_blank">String baseS = "Base";
- //private String baseS = "Base";
- Base(){java/lang/System.java.html" target="_blank">System.out.println("Base()");}
- }
- class Cleanser extends Base{
- protected java/lang/String.java.html" target="_blank">String baseS = "Cleanser";
- public java/lang/String.java.html" target="_blank">String s = new java/lang/String.java.html" target="_blank">String("Cleanser");
- Cleanser(){
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser(): " + s);
- }
- Cleanser(java/lang/String.java.html" target="_blank">String a){
- java/lang/System.java.html" target="_blank">System.out.println("Cleanser(" + a + "): s = " + s );
- }
- }
- public class ExplicitStatic extends Cleanser{
- java/lang/String.java.html" target="_blank">String s2 = s;
- java/lang/String.java.html" target="_blank">String baseS = super.baseS;
- ExplicitStatic(){
- super("ExplicitStatic");
- java/lang/System.java.html" target="_blank">System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = "
- + baseS + "super.baseS = " + super.baseS);
- baseS = "ExplicitStatic";
- java/lang/System.java.html" target="_blank">System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS);
- }
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- ExplicitStatic x = new ExplicitStatic();
- }
- }
結(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ì)象本身。如
- class Value{
- int i = 1;
- }
- public class ExplicitStatic extends Cleanser{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- final Value v = new Value();//v.i = 1
- v.i++;//v.i = 2
- //v = new Value();
- }
- }
由于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)行初始化。
- public class ExplicitStatic {
- final int ib;
- final int i = 1;
- ExplicitStatic()
- {
- ib = 2;//(a)
- //i = 3;?。╞)
- java/lang/System.java.html" target="_blank">System.out.println("i = " + i + ", ib = " + ib);
- }
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- ExplicitStatic ex = new ExplicitStatic();
- }
- }
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,可以被改變。如
- class SmallBrain{}
-
- final class Dinosaur{
- int i = 7;
- int j = i;
- SmallBrain x = new SmallBrain();
- void f(){};
- }
-
- //不能繼承final函數(shù)
- //class Further extends Dinosaur{}
-
- public class ExplicitStatic{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- Dinosaur n = new Dinosaur();
- n.f();
- n.i = 40;//final class中的non-final數(shù)據(jù)成員可以被改變
- n.j++;
- }
- }
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ù)。如
- class First{
- public void prt(){
- java/lang/System.java.html" target="_blank">System.out.println("First");
- }
- }
- class Second extends First{
- //(a)
- public void prt(){
- java/lang/System.java.html" target="_blank">System.out.println("Second");
- }
- }
- public class ExplicitStatic{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- First n = new Second();
- n.prt();;
- }
- }
結(jié)果為Second。如果當(dāng)Second class中的prt()函數(shù)注釋掉,將輸出First。 2. 向上轉(zhuǎn)型后只能調(diào)用base class中被derived class覆寫的函數(shù)。
- /*
- abstract class First{
- int i = 122;
- public void prt(){
- System.out.println("First.i = " + i);
- }
- public abstract void prt(First f);
- }
-
- class Second extends First{
- public void prt(){
- System.out.println("Second.i = " + i);
- }
-
- public void prt(First i)
- {
-
- }
-
- public void prt(int i)
- {
-
- }
- }
- public class ExplicitStatic{
- public static void main(String[] args){
- First n = new Second();
- n.prt(2);;
- }
- }
- */
- class First{
- public void prt(){
- java/lang/System.java.html" target="_blank">System.out.println("First");
- }
- }
- class Second extends First{
- //(a)
- public void prt(){
- java/lang/System.java.html" target="_blank">System.out.println("Second");
- }
- public void prt(int i){//(a)
- java/lang/System.java.html" target="_blank">System.out.println("Second.i = " + i);
- }
- }
- public class ExplicitStatic{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- First n = new Second();
- n.prt(3);
- }
- }
(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ù)
- abstract class First{
- public abstract void f();
- public abstract void g();
- }
- //純粹繼承
- class Second extends First{
- public void f(){}
- public void g(){}
- }
- //擴(kuò)充
- class Third extends First{
- public void f(){}
- public void g(){}
- public void u(){}//base class不存在的函數(shù)
- }
2. 向下轉(zhuǎn)型 1) 向下轉(zhuǎn)型時(shí)只能調(diào)用base class中被覆寫過的函數(shù) 2) 只有本來就為derived class對(duì)象時(shí)才能正確向下轉(zhuǎn)弄。
- class First{
- public void f(){}
- public void g(){}
- }
- class Second extends First{
- public void f(){}
- public void g(){}
- public void u(){}
- public void v(){}
- }
- public class ExplicitStatic{
- public static void main(java/lang/String.java.html" target="_blank">String[] args){
- First[] x = {new First(), new Second()};
- x[0].f();
- x[1].g();
- //!x[1].u();class First中不存在函數(shù)u()
- //((Second)x[0]).f();(a)
- ((Second)x[1]).u();
- }
- }
-------------------------------------
|
|
|
|
|
|
|
|