1. 程式人生 > 其它 >c++提供的可有效分配物件空間的運算子是_第2章一切都是物件

c++提供的可有效分配物件空間的運算子是_第2章一切都是物件

技術標籤:c++提供的可有效分配物件空間的運算子是物件可以建立陣列嗎頻繁的new同一個型別物件

b4e758d9f1540971807d7668ca7262e7.gif

第2章一切都是物件

“儘管以C++為基礎,但Java是一種更純粹的面向物件程式設計語言”。

無論C++還是Java都屬於雜合語言。但在Java中,設計者覺得這種雜合併不象在C++裡那麼重要。雜合語言允許採用多種程式設計風格;之所以說C++是一種雜合語言,是因為它支援與C語言的向後相容能力。由於C++是C的一個超集,所以包含的許多特性都是後者不具備的,這些特性使C++在某些地方顯得過於複雜。

Java語言首先便假定了我們只希望進行面向物件的程式設計。也就是說,正式用它設計之前,必須先將自己的思想轉入一個面向物件的世界(除非早已習慣了這個世界的思維方式)。只有做好這個準備工作,與其他OOP語言相比,才能體會到Java的易學易用。在本章,我們將探討Java程式的基本元件,並體會為什麼說Java乃至Java程式內的一切都是物件。

2.1 用控制代碼操縱物件

每種程式語言都有自己的資料處理方式。有些時候,程式設計師必須時刻留意準備處理的是什麼型別。您曾利用一些特殊語法直接操作過物件,或處理過一些間接表示的物件嗎(C或C++裡的指標)?

所有這些在Java裡都得到了簡化,任何東西都可看作物件。因此,我們可採用一種統一的語法,任何地方均可照搬不誤。但要注意,儘管將一切都“看作”物件,但操縱的識別符號實際是指向一個物件的“控制代碼”(Handle)。在其他Java參考書裡,還可看到有的人將其稱作一個“引用”,甚至一個“指標”。可將這一情形想象成用遙控板(控制代碼)操縱電視機(物件)。只要握住這個遙控板,就相當於掌握了與電視機連線的通道。但一旦需要“換頻道”或者“關小聲音”,我們實際操縱的是遙控板(控制代碼),再由遙控板自己操縱電視機(物件)。如果要在房間裡四處走走,並想保持對電視機的控制,那麼手上拿著的是遙控板,而非電視機。

此外,即使沒有電視機,遙控板亦可獨立存在。也就是說,只是由於擁有一個控制代碼,並不表示必須有一個物件同它連線。所以如果想容納一個詞或句子,可建立一個String控制代碼:

String s;

但這裡建立的只是控制代碼,並不是物件。若此時向s傳送一條訊息,就會獲得一個錯誤(執行期)。這是由於s實際並未與任何東西連線(即“沒有電視機”)。因此,一種更安全的做法是:建立一個控制代碼時,記住無論如何都進行初始化:

String s = "asdf";

然而,這裡採用的是一種特殊型別:字串可用加引號的文字初始化。通常,必須為物件使用一種更通用的初始化型別。

2.2 所有物件都必須建立

建立控制代碼時,我們希望它同一個新物件連線。通常用new關鍵字達到這一目的。new的意思是:“把我變成這些物件的一種新型別”。所以在上面的例子中,可以說:

String s = newString("asdf");

它不僅指出“將我變成一個新字串”,也通過提供一個初始字串,指出了“如何生成這個新字串”。

當然,字串(String)並非唯一的型別。Java配套提供了數量眾多的現成型別。對我們來講,最重要的就是記住能自行建立型別。事實上,這應是Java程式設計的一項基本操作,是繼續本書後餘部分學習的基礎。

2.2.1 儲存到什麼地方

程式執行時,我們最好對資料儲存到什麼地方做到心中有數。特別要注意的是記憶體的分配。有六個地方都可以儲存資料:

(1) 暫存器。這是最快的儲存區域,因為它位於和其他所有儲存方式不同的地方:處理器內部。然而,暫存器的數量十分有限,所以暫存器是根據需要由編譯器分配。我們對此沒有直接的控制權,也不可能在自己的程式裡找到暫存器存在的任何蹤跡。

(2) 堆疊。駐留於常規RAM(隨機訪問儲存器)區域,但可通過它的“堆疊指標”獲得處理的直接支援。堆疊指標若向下移,會建立新的記憶體;若向上移,則會釋放那些記憶體。這是一種特別快、特別有效的資料儲存方式,僅次於暫存器。建立程式時,Java編譯器必須準確地知道堆疊內儲存的所有資料的“長度”以及“存在時間”。這是由於它必須生成相應的程式碼,以便向上和向下移動指標。這一限制無疑影響了程式的靈活性,所以儘管有些Java資料要儲存在堆疊裡——特別是物件控制代碼,但Java物件並不放到其中。

(3) 堆。一種常規用途的記憶體池(也在RAM區域),其中儲存了Java物件。和堆疊不同,“記憶體堆”或“堆”(Heap)最吸引人的地方在於編譯器不必知道要從堆裡分配多少儲存空間,也不必知道儲存的資料要在堆裡停留多長的時間。因此,用堆儲存資料時會得到更大的靈活性。要求建立一個物件時,只需用new命令編制相關的程式碼即可。執行這些程式碼時,會在堆裡自動進行資料的儲存。當然,為達到這種靈活性,必然會付出一定的代價:在堆裡分配儲存空間時會花掉更長的時間!

(4) 靜態儲存。這兒的“靜態”(Static)是指“位於固定位置”(儘管也在RAM裡)。程式執行期間,靜態儲存的資料將隨時等候呼叫。可用static關鍵字指出一個物件的特定元素是靜態的。但Java物件本身永遠都不會置入靜態儲存空間。

(5) 常數儲存。常數值通常直接置於程式程式碼內部。這樣做是安全的,因為它們永遠都不會改變。有的常數需要嚴格地保護,所以可考慮將它們置入只讀儲存器(ROM)。

(6) 非RAM儲存。若資料完全獨立於一個程式之外,則程式不執行時仍可存在,並在程式的控制範圍之外。其中兩個最主要的例子便是“流式物件”和“固定物件”。對於流式物件,物件會變成位元組流,通常會發給另一臺機器。而對於固定物件,物件儲存在磁碟中。即使程式中止執行,它們仍可保持自己的狀態不變。對於這些型別的資料儲存,一個特別有用的技巧就是它們能存在於其他媒體中。一旦需要,甚至能將它們恢復成普通的、基於RAM的物件。Java 1.1提供了對Lightweight persistence的支援。未來的版本甚至可能提供更完整的方案。

2.2.2 特殊情況:主要型別

有一系列類需特別對待;可將它們想象成“基本”、“主要”或者“主”(Primitive)型別,進行程式設計時要頻繁用到它們。之所以要特別對待,是由於用new建立物件(特別是小的、簡單的變數)並不是非常有效,因為new將物件置於“堆”裡。對於這些型別,Java採納了與C和C++相同的方法。也就是說,不是用new建立變數,而是建立一個並非控制代碼的“自動”變數。這個變數容納了具體的值,並置於堆疊中,能夠更高效地存取。

Java決定了每種主要型別的大小。就象在大多數語言裡那樣,這些大小並不隨著機器結構的變化而變化。這種大小的不可更改正是Java程式具有很強移植能力的原因之一。

主型別大小最小值最大值封裝器型別

boolean 1位 - - Boolean

char 16位 Unicode 0 Unicode 2的16次方-1 Character

byte 8位 -128 +127 Byte(註釋①)

short 16位 -2的15次方 +2的15次方-1 Short(註釋①)

int 32位 -2的31次方 +2的31次方-1 Integer

long 64位 -2的63次方 +2的63次方-1 Long

float 32位 IEEE754 IEEE754 Float

double 64位 IEEE754 IEEE754 Double

Void - - - Void(註釋①)

①:到Java 1.1才有,1.0版沒有。

數值型別全都是有符號(正負號)的,所以不必費勁尋找沒有符號的型別。

主資料型別也擁有自己的“封裝器”(wrapper)類。這意味著假如想讓堆內一個非主要物件表示那個主型別,就要使用對應的封裝器。例如:

char c = 'x';

Character C = new Character('c');

也可以直接使用:

Character C = new Character('x');

這樣做的原因將在以後的章節裡解釋。

1. 高精度數字

Java 1.1增加了兩個類,用於進行高精度的計算:BigInteger和BigDecimal。儘管它們大致可以劃分為“封裝器”型別,但兩者都沒有對應的“主型別”。

這兩個類都有自己特殊的“方法”,對應於我們針對主型別執行的操作。也就是說,能對int或float做的事情,對BigInteger和BigDecimal一樣可以做。只是必須使用方法呼叫,不能使用運算子。此外,由於牽涉更多,所以運算速度會慢一些。我們犧牲了速度,但換來了精度。

BigInteger支援任意精度的整數。也就是說,我們可精確表示任意大小的整數值,同時在運算過程中不會丟失任何資訊。

BigDecimal支援任意精度的定點數字。例如,可用它進行精確的幣值計算。

至於呼叫這兩個類時可選用的構建器和方法,請自行參考聯機幫助文件。

2.2.3 Java的陣列

幾乎所有程式設計語言都支援陣列。在C和C++裡使用陣列是非常危險的,因為那些陣列只是記憶體塊。若程式訪問自己記憶體塊以外的陣列,或者在初始化之前使用記憶體(屬於常規程式設計錯誤),會產生不可預測的後果(註釋②)。

②:在C++裡,應儘量不要使用陣列,換用標準模板庫(Standard TemplateLibrary)裡更安全的容器。

Java的一項主要設計目標就是安全性。所以在C和C++裡困擾程式設計師的許多問題都未在Java裡重複。一個Java可以保證被初始化,而且不可在它的範圍之外訪問。由於系統自動進行範圍檢查,所以必然要付出一些代價:針對每個陣列,以及在執行期間對索引的校驗,都會造成少量的記憶體開銷。但由此換回的是更高的安全性,以及更高的工作效率。為此付出少許代價是值得的。

建立物件陣列時,實際建立的是一個控制代碼陣列。而且每個控制代碼都會自動初始化成一個特殊值,並帶有自己的關鍵字:null(空)。一旦Java看到null,就知道該控制代碼並未指向一個物件。正式使用前,必須為每個控制代碼都分配一個物件。若試圖使用依然為null的一個控制代碼,就會在執行期報告問題。因此,典型的陣列錯誤在Java裡就得到了避免。

也可以建立主型別陣列。同樣地,編譯器能夠擔保對它的初始化,因為會將那個陣列的記憶體劃分成零。

陣列問題將在以後的章節裡詳細討論。

2.3 絕對不要清除物件

在大多數程式設計語言中,變數的“存在時間”(Lifetime)一直是程式設計師需要著重考慮的問題。變數應持續多長的時間?如果想清除它,那麼何時進行?在變數存在時間上糾纏不清會造成大量的程式錯誤。在下面的小節裡,將闡示Java如何幫助我們完成所有清除工作,從而極大了簡化了這個問題。

2.3.1 作用域

大多數程式設計語言都提供了“作用域”(Scope)的概念。對於在作用域裡定義的名字,作用域同時決定了它的“可見性”以及“存在時間”。在C,C++和Java裡,作用域是由花括號的位置決定的。參考下面這個例子:

{

int x = 12;

/* only x available */

{

int q = 96;

/* both x & q available */

}

/* only x available */

/* q “out of scope” */

}

73頁程式

作為在作用域裡定義的一個變數,它只有在那個作用域結束之前才可使用。

在上面的例子中,縮排排版使Java程式碼更易辨讀。由於Java是一種形式自由的語言,所以額外的空格、製表位以及回車都不會對結果程式造成影響。

注意儘管在C和C++裡是合法的,但在Java裡不能象下面這樣書寫程式碼:

{

int x = 12;

{

int x = 96; /* illegal */

}

}

74頁上程式

編譯器會認為變數x已被定義。所以C和C++能將一個變數“隱藏”在一個更大的作用域裡。但這種做法在Java裡是不允許的,因為Java的設計者認為這樣做使程式產生了混淆。

2.3.2 物件的作用域

Java物件不具備與主型別一樣的存在時間。用new關鍵字建立一個Java物件的時候,它會超出作用域的範圍之外。所以假若使用下面這段程式碼:

{

String s = newString("a string");

} /* 作用域的終點 */

那麼控制代碼s會在作用域的終點處消失。然而,s指向的String物件依然佔據著記憶體空間。在上面這段程式碼裡,我們沒有辦法訪問物件,因為指向它的唯一一個控制代碼已超出了作用域的邊界。在後面的章節裡,大家還會繼續學習如何在程式執行期間傳遞和複製物件控制代碼。

這樣造成的結果便是:對於用new建立的物件,只要我們願意,它們就會一直保留下去。這個程式設計問題在C和C++裡特別突出。看來在C++裡遇到的麻煩最大:由於不能從語言獲得任何幫助,所以在需要物件的時候,根本無法確定它們是否可用。而且更麻煩的是,在C++裡,一旦工作完成,必須保證將物件清除。

這樣便帶來了一個有趣的問題。假如Java讓物件依然故我,怎樣才能防止它們大量充斥記憶體,並最終造成程式的“凝固”呢。在C++裡,這個問題最令程式設計師頭痛。但Java以後,情況卻發生了改觀。Java有一個特別的“垃圾收集器”,它會查詢用new建立的所有物件,並辨別其中哪些不再被引用。隨後,它會自動釋放由那些閒置物件佔據的記憶體,以便能由新物件使用。這意味著我們根本不必操心記憶體的回收問題。只需簡單地建立物件,一旦不再需要它們,它們就會自動離去。這樣做可防止在C++裡很常見的一個程式設計問題:由於程式設計師忘記釋放記憶體造成的“記憶體溢位”。

2.4 新建資料型別:類

如果說一切東西都是物件,那麼用什麼決定一個“類”(Class)的外觀與行為呢?換句話說,是什麼建立起了一個物件的“型別”(Type)呢?大家可能猜想有一個名為“type”的關鍵字。但從歷史看來,大多數面向物件的語言都用關鍵字“class”表達這樣一個意思:“我準備告訴你物件一種新型別的外觀”。class關鍵字太常用了,以至於本書許多地方並沒有用粗體字或雙引號加以強調。在這個關鍵字的後面,應該跟隨新資料型別的名稱。例如:

class ATypeName {/*類主體置於這裡}

這樣就引入了一種新型別,接下來便可用new建立這種型別的一個新物件:

ATypeName a = new ATypeName();

在ATypeName裡,類主體只由一條註釋構成(星號和斜槓以及其中的內容,本章後面還會詳細講述),所以並不能對它做太多的事情。事實上,除非為其定義了某些方法,否則根本不能指示它做任何事情。

2.4.1 欄位和方法

定義一個類時(我們在Java裡的全部工作就是定義類、製作那些類的物件以及將訊息發給那些物件),可在自己的類裡設定兩種型別的元素:資料成員(有時也叫“欄位”)以及成員函式(通常叫“方法”)。其中,資料成員是一種物件(通過它的控制代碼與其通訊),可以為任何型別。它也可以是主型別(並不是控制代碼)之一。如果是指向物件的一個控制代碼,則必須初始化那個控制代碼,用一種名為“構建器”(第4章會對此詳述)的特殊函式將其與一個實際物件連線起來(就象早先看到的那樣,使用new關鍵字)。但若是一種主型別,則可在類定義位置直接初始化(正如後面會看到的那樣,控制代碼亦可在定義位置初始化)。

每個物件都為自己的資料成員保有儲存空間;資料成員不會在物件之間共享。下面是定義了一些資料成員的類示例:

class DataOnly {

int i;

float f;

boolean b;

}

76頁上程式

這個類並沒有做任何實質性的事情,但我們可建立一個物件:

DataOnly d = new DataOnly();

可將值賦給資料成員,但首先必須知道如何引用一個物件的成員。為達到引用物件成員的目的,首先要寫上物件控制代碼的名字,再跟隨一個點號(句點),再跟隨物件內部成員的名字。即“物件控制代碼.成員”。例如:

d.i = 47;

d.f = 1.1f;

d.b = false;

一個物件也可能包含了另一個物件,而另一個物件裡則包含了我們想修改的資料。對於這個問題,只需保持“連線句點”即可。例如:

myPlane.leftTank.capacity =100;

除容納資料之外,DataOnly類再也不能做更多的事情,因為它沒有成員函式(方法)。為正確理解工作原理,首先必須知道“自變數”和“返回值”的概念。我們馬上就會詳加解釋。

1. 主成員的預設值

若某個主資料型別屬於一個類成員,那麼即使不明確(顯式)進行初始化,也可以保證它們獲得一個預設值。

主型別預設值

Boolean false

Char '\u0000'(null)

byte (byte)0

short (short)0

int 0

long 0L

float 0.0f

double 0.0d

一旦將變數作為類成員使用,就要特別注意由Java分配的預設值。這樣做可保證主型別的成員變數肯定得到了初始化(C++不具備這一功能),可有效遏止多種相關的程式設計錯誤。

然而,這種保證卻並不適用於“區域性”變數——那些變數並非一個類的欄位。所以,假若在一個函式定義中寫入下述程式碼:

int x;

那麼x會得到一些隨機值(這與C和C++是一樣的),不會自動初始化成零。我們責任是在正式使用x前分配一個適當的值。如果忘記,就會得到一條編譯期錯誤,告訴我們變數可能尚未初始化。這種處理正是Java優於C++的表現之一。許多C++編譯器會對變數未初始化發出警告,但在Java裡卻是錯誤。

2.5 方法、自變數和返回值

迄今為止,我們一直用“函式”(Function)這個詞指代一個已命名的子例程。但在Java裡,更常用的一個詞卻是“方法”(Method),代表“完成某事的途徑”。儘管它們表達的實際是同一個意思,但從現在開始,本書將一直使用“方法”,而不是“函式”。

Java的“方法”決定了一個物件能夠接收的訊息。通過本節的學習,大家會知道方法的定義有多麼簡單!

方法的基本組成部分包括名字、自變數、返回型別以及主體。下面便是它最基本的形式:

返回型別方法名( /* 自變數列表*/ ) {/* 方法主體 */}

返回型別是指呼叫方法之後返回的數值型別。顯然,方法名的作用是對具體的方法進行標識和引用。自變數列表列出了想傳遞給方法的資訊型別和名稱。

Java的方法只能作為類的一部分建立。只能針對某個物件呼叫一個方法(註釋③),而且那個物件必須能夠執行那個方法呼叫。若試圖為一個物件呼叫錯誤的方法,就會在編譯期得到一條出錯訊息。為一個物件呼叫方法時,需要先列出物件的名字,在後面跟上一個句點,再跟上方法名以及它的引數列表。亦即“物件名.方法名(自變數1,自變數2,自變數3...)。舉個例子來說,假設我們有一個方法名叫f(),它沒有自變數,返回的是型別為int的一個值。那麼,假設有一個名為a的物件,可為其呼叫方法f(),則程式碼如下:

int x = a.f();

返回值的型別必須相容x的型別。

象這樣呼叫一個方法的行動通常叫作“向物件傳送一條訊息”。在上面的例子中,訊息是f(),而物件是a。面向物件的程式設計通常簡單地歸納為“向物件傳送訊息”。

③:正如馬上就要學到的那樣,“靜態”方法可針對類呼叫,毋需一個物件。

2.5.1 自變數列表

自變數列表規定了我們傳送給方法的是什麼資訊。正如大家或許已猜到的那樣,這些資訊——如同Java內其他任何東西——採用的都是物件的形式。因此,我們必須在自變數列表裡指定要傳遞的物件型別,以及每個物件的名字。正如在Java其他地方處理物件時一樣,我們實際傳遞的是“控制代碼”(註釋④)。然而,控制代碼的型別必須正確。倘若希望自變數是一個“字串”,那麼傳遞的必須是一個字串。

④:對於前面提及的“特殊”資料型別boolean,char,byte,short,int,long,,float以及double來說是一個例外。但在傳遞物件時,通常都是指傳遞指向物件的控制代碼。

下面讓我們考慮將一個字串作為自變數使用的方法。下面列出的是定義程式碼,必須將它置於一個類定義裡,否則無法編譯:

int storage(String s) {

return s.length() * 2;

}

這個方法告訴我們需要多少位元組才能容納一個特定字串裡的資訊(字串裡的每個字元都是16位,或者說2個位元組、長整數,以便提供對Unicode字元的支援)。自變數的型別為String,而且叫作s。一旦將s傳遞給方法,就可將它當作其他物件一樣處理(可向其傳送訊息)。在這裡,我們呼叫的是length()方法,它是String的方法之一。該方法返回的是一個字串裡的字元數。

通過上面的例子,也可以瞭解return關鍵字的運用。它主要做兩件事情。首先,它意味著“離開方法,我已完工了”。其次,假設方法生成了一個值,則那個值緊接在return語句的後面。在這種情況下,返回值是通過計算表示式“s.length()*2”而產生的。

可按自己的願望返回任意型別,但倘若不想返回任何東西,就可指示方法返回void(空)。下面列出一些例子。

boolean flag() { returntrue; }

float naturalLogBase() {return 2.718; }

void nothing() { return; }

void nothing2() {}

若返回型別為void,則return關鍵字唯一的作用就是退出方法。所以一旦抵達方法末尾,該關鍵字便不需要了。可在任何地方從一個方法返回。但假設已指定了一種非void的返回型別,那麼無論從何地返回,編譯器都會確保我們返回的是正確的型別。

到此為止,大家或許已得到了這樣的一個印象:一個程式只是一系列物件的集合,它們的方法將其他物件作為自己的自變數使用,而且將訊息發給那些物件。這種說法大體正確,但通過以後的學習,大家還會知道如何在一個方法裡作出決策,做一些更細緻的基層工作。至於這一章,只需理解訊息傳送就足夠了。

2.6 構建Java程式

正式構建自己的第一個Java程式前,還有幾個問題需要注意。

2.6.1 名字的可見性

在所有程式設計語言裡,一個不可避免的問題是對名字或名稱的控制。假設您在程式的某個模組裡使用了一個名字,而另一名程式設計師在另一個模組裡使用了相同的名字。此時,如何區分兩個名字,並防止兩個名字互相沖突呢?這個問題在C語言裡特別突出。因為程式未提供很好的名字管理方法。C++的類(即Java類的基礎)巢狀使用類裡的函式,使其不至於同其他類裡的巢狀函式名衝突。然而,C++仍然允許使用全域性資料以及全域性函式,所以仍然難以避免衝突。為解決這個問題,C++用額外的關鍵字引入了“名稱空間”的概念。

由於採用全新的機制,所以Java能完全避免這些問題。為了給一個庫生成明確的名字,採用了與Internet域名類似的名字。事實上,Java的設計者鼓勵程式設計師反轉使用自己的Internet域名,因為它們肯定是獨一無二的。由於我的域名是BruceEckel.com,所以我的實用工具庫就可命名為com.bruceeckel.utility.foibles。反轉了域名後,可將點號想象成子目錄。

在Java 1.0和Java 1.1中,域副檔名com,edu,org,net等都約定為大寫形式。所以庫的樣子就變成:COM.bruceeckel.utility.foibles。然而,在Java 1.2的開發過程中,設計者發現這樣做會造成一些問題。所以目前的整個軟體包都以小寫字母為標準。

Java的這種特殊機制意味著所有檔案都自動存在於自己的名稱空間裡。而且一個檔案裡的每個類都自動獲得一個獨一無二的識別符號(當然,一個檔案裡的類名必須是唯一的)。所以不必學習特殊的語言知識來解決這個問題——語言本身已幫我們照顧到這一點。

2.6.2 使用其他元件

一旦要在自己的程式裡使用一個預先定義好的類,編譯器就必須知道如何找到它。當然,這個類可能就在發出呼叫的那個相同的原始碼檔案裡。如果是那種情況,只需簡單地使用這個類即可——即使它直到檔案的後面仍未得到定義。Java消除了“向前引用”的問題,所以不要關心這些事情。

但假若那個類位於其他檔案裡呢?您或許認為編譯器應該足夠“聯盟”,可以自行發現它。但實情並非如此。假設我們想使用一個具有特定名稱的類,但那個類的定義位於多個檔案裡。或者更糟,假設我們準備寫一個程式,但在建立它的時候,卻向自己的庫加入了一個新類,它與現有某個類的名字發生了衝突。

為解決這個問題,必須消除所有潛在的、糾纏不清的情況。為達到這個目的,要用import關鍵字準確告訴Java編譯器我們希望的類是什麼。import的作用是指示編譯器匯入一個“包”——或者說一個“類庫”(在其他語言裡,可將“庫”想象成一系列函式、資料以及類的集合。但請記住,Java的所有程式碼都必須寫入一個類中)。

大多數時候,我們直接採用來自標準Java庫的元件(部件)即可,它們是與編譯器配套提供的。使用這些元件時,沒有必要關心冗長的保留域名;舉個例子來說,只需象下面這樣寫一行程式碼即可:

import java.util.Vector;

它的作用是告訴編譯器我們想使用Java的Vector類。然而,util包含了數量眾多的類,我們有時希望使用其中的幾個,同時不想全部明確地宣告它們。為達到這個目的,可使用“*”萬用字元。如下所示:

import java.util.*;

需匯入一系列類時,採用的通常是這個辦法。應儘量避免一個一個地匯入類。

2.6.3 static關鍵字

通常,我們建立類時會指出那個類的物件的外觀與行為。除非用new建立那個類的一個物件,否則實際上並未得到任何東西。只有執行了new後,才會正式生成資料儲存空間,並可使用相應的方法。

但在兩種特殊的情形下,上述方法並不堪用。一種情形是隻想用一個儲存區域來儲存一個特定的資料——無論要建立多少個物件,甚至根本不建立物件。另一種情形是我們需要一個特殊的方法,它沒有與這個類的任何物件關聯。也就是說,即使沒有建立物件,也需要一個能呼叫的方法。為滿足這兩方面的要求,可使用static(靜態)關鍵字。一旦將什麼東西設為static,資料或方法就不會同那個類的任何物件例項聯絡到一起。所以儘管從未建立那個類的一個物件,仍能呼叫一個static方法,或訪問一些static資料。而在這之前,對於非static資料和方法,我們必須建立一個物件,並用那個物件訪問資料或方法。這是由於非static資料和方法必須知道它們操作的具體物件。當然,在正式使用前,由於static方法不需要建立任何物件,所以它們不可簡單地呼叫其他那些成員,同時不引用一個已命名的物件,從而直接訪問非static成員或方法(因為非static成員和方法必須同一個特定的物件關聯到一起)。

有些面向物件的語言使用了“類資料”和“類方法”這兩個術語。它們意味著資料和方法只是為作為一個整體的類而存在的,並不是為那個類的任何特定物件。有時,您會在其他一些Java書刊裡發現這樣的稱呼。

為了將資料成員或方法設為static,只需在定義前置和這個關鍵字即可。例如,下述程式碼能生成一個static資料成員,並對其初始化:

class StaticTest {

Static int i = 47;

}

現在,儘管我們製作了兩個StaticTest物件,但它們仍然只佔據StaticTest.i的一個儲存空間。這兩個物件都共享同樣的i。請考察下述程式碼:

StaticTest st1 = new StaticTest();

StaticTest st2 = new StaticTest();

此時,無論st1.i還是st2.i都有同樣的值47,因為它們引用的是同樣的記憶體區域。

有兩個辦法可引用一個static變數。正如上面展示的那樣,可通過一個物件命名它,如st2.i。亦可直接用它的類名引用,而這在非靜態成員裡是行不通的(最好用這個辦法引用static變數,因為它強調了那個變數的“靜態”本質)。

StaticTest.i++;

其中,++運算子會使變數增值。此時,無論st1.i還是st2.i的值都是48。

類似的邏輯也適用於靜態方法。既可象對其他任何方法那樣通過一個物件引用靜態方法,亦可用特殊的語法格式“類名.方法()”加以引用。靜態方法的定義是類似的:

class StaticFun {

static void incr() { StaticTest.i++; }

}

從中可看出,StaticFun的方法incr()使靜態資料i增值。通過物件,可用典型的方法呼叫incr():

StaticFun sf = new StaticFun();

sf.incr();

或者,由於incr()是一種靜態方法,所以可通過它的類直接呼叫:

StaticFun.incr();

儘管是“靜態”的,但只要應用於一個數據成員,就會明確改變資料的建立方式(一個類一個成員,以及每個物件一個非靜態成員)。若應用於一個方法,就沒有那麼戲劇化了。對方法來說,static一項重要的用途就是幫助我們在不必建立物件的前提下呼叫那個方法。正如以後會看到的那樣,這一點是至關重要的——特別是在定義程式執行入口方法main()的時候。

和其他任何方法一樣,static方法也能建立自己型別的命名物件。所以經常把static方法作為一個“領頭羊”使用,用它生成一系列自己型別的“例項”。

2.7 我們的第一個Java程式

最後,讓我們正式編一個程式(註釋⑤)。它能打印出與當前執行的系統有關的資料,並利用了來自Java標準庫的System物件的多種方法。注意這裡引入了一種額外的註釋樣式:“//”。它表示到本行結束前的所有內容都是註釋:

// HelloDate.java

import java.util.*;

public class HelloDate {

public static void main(String[] args) {

System.out.println("Hello,it's: ");

System.out.println(new Date());

}

}

84頁程式

⑤:在某些程式設計環境裡,程式會在螢幕上一切而過,甚至沒機會看到結果。可將下面這段程式碼置於main()的末尾,用它暫停輸出:

try {

Thread.currentThread().sleep(5* 1000);

} catch(InterruptedExceptione) {}

}

它的作用是暫停輸出5秒鐘。這段程式碼涉及的一些概念要到本書後面才會講到。所以目前不必深究,只知道它是讓程式暫停的一個技巧便可。

在每個程式檔案的開頭,都必須放置一個import語句,匯入那個檔案的程式碼裡要用到的所有額外的類。注意我們說它們是“額外”的,因為一個特殊的類庫會自動匯入每個Java檔案:java.lang。啟動您的Web瀏覽器,檢視由Sun提供的使用者文件(如果尚未從http://www.java.sun.com下載,或用其他方式安裝了Java文件,請立即下載)。在packages.html檔案裡,可找到Java配套提供的所有類庫名稱。請選擇其中的java.lang。在“Class Index”下面,可找到屬於那個庫的全部類的列表。由於java.lang預設進入每個Java程式碼檔案,所以這些類在任何時候都可直接使用。在這個列表裡,可發現System和Runtime,我們在Property.java裡用到了它們。java.lang裡沒有列出Date類,所以必須匯入另一個類庫才能使用它。如果不清楚一個特定的類在哪個類庫裡,或者想檢視所有的類,可在Java使用者文件裡選擇“Class Hierarchy”(類分級結構)。在Web瀏覽器中,雖然要花不短的時間來建立這個結構,但可清楚找到與Java配套提供的每一個類。隨後,可用瀏覽器的“查詢”(Find)功能搜尋關鍵字“Date”。經這樣處理後,可發現我們的搜尋目標以java.util.Date的形式列出。我們終於知道它位於util庫裡,所以必須匯入java.util.*;否則便不能使用Date。

觀察packages.html文件最開頭的部分(我已將其設為自己的預設起始頁),請選擇java.lang,再選System。這時可看到System類有幾個欄位。若選擇out,就可知道它是一個static PrintStream物件。由於它是“靜態”的,所以不需要我們建立任何東西。out物件肯定是3,所以只需直接用它即可。我們能對這個out物件做的事情由它的型別決定:PrintStream。PrintStream在說明文字中以一個超連結的形式列出,這一點做得非常方便。所以假若單擊那個連結,就可看到能夠為PrintStream呼叫的所有方法。方法的數量不少,本書後面會詳細介紹。就目前來說,我們感興趣的只有println()。它的意思是“把我給你的東西列印到控制檯,並用一個新行結束”。所以在任何Java程式中,一旦要把某些內容列印到控制檯,就可條件反射地寫上System.out.println("內容")。

類名與檔案是一樣的。若象現在這樣建立一個獨立的程式,檔案中的一個類必須與檔案同名(如果沒這樣做,編譯器會及時作出反應)。類裡必須包含一個名為main()的方法,形式如下:

public static void main(String[] args){

其中,關鍵字“public”意味著方法可由外部世界呼叫(第5章會詳細解釋)。main()的自變數是包含了String物件的一個數組。args不會在本程式中用到,但需要在這個地方列出,因為它們儲存了在命令列呼叫的自變數。

程式的第一行非常有趣:

System.out.println(new Date());

請觀察它的自變數:建立Date物件唯一的目的就是將它的值傳送給println()。一旦這個語句執行完畢,Date就不再需要。隨之而來的“垃圾收集器”會發現這一情況,並在任何可能的時候將其回收。事實上,我們沒太大的必要關心“清除”的細節。

第二行呼叫了System.getProperties()。若用Web瀏覽器檢視聯機使用者文件,就可知道getProperties()是System類的一個static方法。由於它是“靜態”的,所以不必建立任何物件便可呼叫該方法。無論是否存在該類的一個物件,static方法隨時都可使用。呼叫getProperties()時,它會將系統屬性作為Properties類的一個物件生成(注意Properties是“屬性”的意思)。隨後的的控制代碼儲存在一個名為p的Properties控制代碼裡。在第三行,大家可看到Properties物件有一個名為list()的方法,它將自己的全部內容都發給一個我們作為自變數傳遞的PrintStream物件。

main()的第四和第六行是典型的列印語句。注意為了列印多個String值,用加號(+)分隔它們即可。然而,也要在這裡注意一些奇怪的事情。在String物件中使用時,加號並不代表真正的“相加”。處理字串時,我們通常不必考慮“+”的任何特殊含義。但是,Java的String類要受一種名為“運算子過載”的機制的制約。也就是說,只有在隨同String物件使用時,加號才會產生與其他任何地方不同的表現。對於字串,它的意思是“連線這兩個字串”。

但事情到此並未結束。請觀察下述語句:

System.out.println("Total Memory ="

+ rt.totalMemory()

+ " Free Memory = "

+ rt.freeMemory());

其中,totalMemory()和freeMemory()返回的是數值,並非String物件。如果將一個數值“加”到一個字串身上,會發生什麼情況呢?同我們一樣,編譯器也會意識到這個問題,並魔術般地呼叫一個方法,將那個數值(int,float等等)轉換成字串。經這樣處理後,它們當然能利用加號“加”到一起。這種“自動型別轉換”亦劃入“運算子過載”處理的範疇。

許多Java著作都在熱烈地辯論“運算子過載”(C++的一項特性)是否有用。目前就是反對它的一個好例子!然而,這最多隻能算編譯器(程式)的問題,而且只是對String物件而言。對於自己編寫的任何原始碼,都不可能使運算子“過載”。

通過為Runtime類呼叫getRuntime()方法,main()的第五行建立了一個Runtime物件。返回的則是指向一個Runtime物件的控制代碼。而且,我們不必關心它是一個靜態物件,還是由new命令建立的一個物件。這是由於我們不必為清除工作負責,可以大模大樣地使用物件。正如顯示的那樣,Runtime可告訴我們與記憶體使用有關的資訊。

2.8 註釋和嵌入文件

Java裡有兩種型別的註釋。第一種是傳統的、C語言風格的註釋,是從C++繼承而來的。這些註釋用一個“/*”起頭,隨後是註釋內容,並可跨越多行,最後用一個“*/”結束。注意許多程式設計師在連續註釋內容的每一行都用一個“*”開頭,所以經常能看到象下面這樣的內容:

/* 這是

* 一段註釋,

* 它跨越了多個行

*/

但請記住,進行編譯時,/*和*/之間的所有東西都會被忽略,所以上述註釋與下面這段註釋並沒有什麼不同:

/* 這是一段註釋,

它跨越了多個行 */

第二種型別的註釋也起源於C++。這種註釋叫作“單行註釋”,以一個“//”起頭,表示這一行的所有內容都是註釋。這種型別的註釋更常用,因為它書寫時更方便。沒有必要在鍵盤上尋找“/”,再尋找“*”(只需按同樣的鍵兩次),而且不必在註釋結尾時加一個結束標記。下面便是這類註釋的一個例子:

// 這是一條單行註釋

2.8.1 註釋文件

對於Java語言,最體貼的一項設計就是它並沒有打算讓人們為了寫程式而寫程式——人們也需要考慮程式的文件化問題。對於程式的文件化,最大的問題莫過於對文件的維護。若文件與程式碼分離,那麼每次改變程式碼後都要改變文件,這無疑會變成相當麻煩的一件事情。解決的方法看起來似乎很簡單:將程式碼同文檔“連結”起來。為達到這個目的,最簡單的方法是將所有內容都置於同一個檔案。然而,為使一切都整齊劃一,還必須使用一種特殊的註釋語法,以便標記出特殊的文件;另外還需要一個工具,用於提取這些註釋,並按有價值的形式將其展現出來。這些都是Java必須做到的。

用於提取註釋的工具叫作javadoc。它採用了部分來自Java編譯器的技術,查詢我們置入程式的特殊註釋標記。它不僅提取由這些標記指示的資訊,也將毗鄰註釋的類名或方法名提取出來。這樣一來,我們就可用最輕的工作量,生成十分專業的程式文件。

javadoc輸出的是一個HTML檔案,可用自己的Web瀏覽器檢視。該工具允許我們建立和管理單個原始檔,並生動生成有用的文件。由於有了jvadoc,所以我們能夠用標準的方法建立文件。而且由於它非常方便,所以我們能輕鬆獲得所有Java庫的文件。

2.8.2 具體語法

所有javadoc命令都只能出現於“/**”註釋中。但和平常一樣,註釋結束於一個“*/”。主要通過兩種方式來使用javadoc:嵌入的HTML,或使用“文件標記”。其中,“文件標記”(Doc tags)是一些以“@”開頭的命令,置於註釋行的起始處(但前導的“*”會被忽略)。

有三種類型的註釋文件,它們對應於位於註釋後面的元素:類、變數或者方法。也就是說,一個類註釋正好位於一個類定義之前;變數註釋正好位於變數定義之前;而一個方法定義正好位於一個方法定義的前面。如下面這個簡單的例子所示:

/** 一個類註釋 */

public class docTest {

/** 一個變數註釋 */

public int i;

/** 一個方法註釋 */

public void f() {}

}

注意javadoc只能為public(公共)和protected(受保護)成員處理註釋文件。“private”(私有)和“友好”(詳見5章)成員的註釋會被忽略,我們看不到任何輸出(也可以用-private標記包括private成員)。這樣做是有道理的,因為只有public和protected成員才可在檔案之外使用,這是客戶程式設計師的希望。然而,所有類註釋都會包含到輸出結果裡。

上述程式碼的輸出是一個HTML檔案,它與其他Java文件具有相同的標準格式。因此,使用者會非常熟悉這種格式,可在您設計的類中方便地“漫遊”。設計程式時,請務必考慮輸入上述程式碼,用javadoc處理一下,觀看最終HTML檔案的效果如何。

2.8.3 嵌入HTML

javadoc將HTML命令傳遞給最終生成的HTML文件。這便使我們能夠充分利用HTML的巨大威力。當然,我們的最終動機是格式化程式碼,不是為了譁眾取寵。下面列出一個例子:

/**

*

* System.out.println(new Date());

*

*/

亦可象在其他Web文件裡那樣運用HTML,對普通文字進行格式化,使其更具條理、更加美觀:

/**

* 您甚至可以插入一個列表:

*

* 專案一

* 專案二

* 專案三

*

*/

注意在文件註釋中,位於一行最開頭的星號會被javadoc丟棄。同時丟棄的還有前導空格。javadoc會對所有內容進行格式化,使其與標準的文件外觀相符。不要將

或 這樣的標題當作嵌入 HTML 使用,因為 javadoc 會插入自己的標題,我們給出的標題會與之衝撞。

所有型別的註釋文件——類、變數和方法——都支援嵌入HTML。

2.8.4 @see:引用其他類

所有三種類型的註釋文件都可包含@see標記,它允許我們引用其他類裡的文件。對於這個標記,javadoc會生成相應的HTML,將其直接連結到其他文件。格式如下:

@see 類名

@see 完整類名

@see 完整類名#方法名

每一格式都會在生成的文件裡自動加入一個超連結的“See Also”(參見)條目。注意javadoc不會檢查我們指定的超連結,不會驗證它們是否有效。

2.8.5 類文件標記

隨同嵌入HTML和@see引用,類文件還可以包括用於版本資訊以及作者姓名的標記。類文件亦可用於“介面”目的(本書後面會詳細解釋)。

1. @version

格式如下:

@version 版本資訊

其中,“版本資訊”代表任何適合作為版本說明的資料。若在javadoc命令列使用了“-version”標記,就會從生成的HTML文件裡提取出版本資訊。

2. @author

格式如下:

@author 作者資訊

其中,“作者資訊”包括您的姓名、電子函件地址或者其他任何適宜的資料。若在javadoc命令列使用了“-author”標記,就會專門從生成的HTML文件裡提取出作者資訊。

可為一系列作者使用多個這樣的標記,但它們必須連續放置。全部作者資訊會一起存入最終HTML程式碼的單獨一個段落裡。

2.8.6 變數文件標記

變數文件只能包括嵌入的HTML以及@see引用。

2.8.7 方法文件標記

除嵌入HTML和@see引用之外,方法還允許使用針對引數、返回值以及違例的文件標記。

1. @param

格式如下:

@param 引數名說明

其中,“引數名”是指引數列表內的識別符號,而“說明”代表一些可延續到後續行內的說明文字。一旦遇到一個新文件標記,就認為前一個說明結束。可使用任意數量的說明,每個引數一個。

2. @return

格式如下:

@return 說明

其中,“說明”是指返回值的含義。它可延續到後面的行內。

3. @exception

有關“違例”(Exception)的詳細情況,我們會在第9章講述。簡言之,它們是一些特殊的物件,若某個方法失敗,就可將它們“扔出”物件。呼叫一個方法時,儘管只有一個違例物件出現,但一些特殊的方法也許能產生任意數量的、不同型別的違例。所有這些違例都需要說明。所以,違例標記的格式如下:

@exception 完整類名說明

其中,“完整類名”明確指定了一個違例類的名字,它是在其他某個地方定義好的。而“說明”(同樣可以延續到下面的行)告訴我們為什麼這種特殊型別的違例會在方法呼叫中出現。

4. @deprecated

這是Java 1.1的新特性。該標記用於指出一些舊功能已由改進過的新功能取代。該標記的作用是建議使用者不必再使用一種特定的功能,因為未來改版時可能摒棄這一功能。若將一個方法標記為@deprecated,則使用該方法時會收到編譯器的警告。

2.8.8 文件示例

下面還是我們的第一個Java程式,只不過已加入了完整的文件註釋:

//: c02:HelloDate.java

import java.util.*;

/** The first Thinking inJava example program.

* Displays a string and today's date.

* @author Bruce Eckel

* @author http://www.BruceEckel.com

* @version 2.0

*/

public class HelloDate {

/** Sole entry point to class & application

* @param args array of string arguments

* @return No return value

* @exception exceptions No exceptions thrown

*/

public static void main(String[] args) {

System.out.println("Hello, it's:");

System.out.println(new Date());

}

} ///:~

92頁程式

第一行:

//: Property.java

採用了我自己的方法:將一個“:”作為特殊的記號,指出這是包含了原始檔名字的一個註釋行。最後一行也用這樣的一條註釋結尾,它標誌著原始碼清單的結束。這樣一來,可將程式碼從本書的正文中方便地提取出來,並用一個編譯器檢查。這方面的細節在第17章講述。

2.9 編碼樣式

一個非正式的Java程式設計標準是大寫一個類名的首字母。若類名由幾個單詞構成,那麼把它們緊靠到一起(也就是說,不要用下劃線來分隔名字)。此外,每個嵌入單詞的首字母都採用大寫形式。例如:

class AllTheColorsOfTheRainbow { //...}

對於其他幾乎所有內容:方法、欄位(成員變數)以及物件控制代碼名稱,可接受的樣式與類樣式差不多,只是識別符號的第一個字母採用小寫。例如:

class AllTheColorsOfTheRainbow {

int anIntegerRepresentingColors;

void changeTheHueOfTheColor(int newHue){

// ...

}

// ...

}

當然,要注意使用者也必須鍵入所有這些長名字,而且不能輸錯。

2.10 總結

通過本章的學習,大家已接觸了足夠多的Java程式設計知識,已知道如何自行編寫一個簡單的程式。此外,對語言的總體情況以及一些基本思想也有了一定程度的認識。然而,本章所有例子的模式都是單線形式的“這樣做,再那樣做,然後再做另一些事情”。如果想讓程式作出一項選擇,又該如何設計呢?例如,“假如這樣做的結果是紅色,就那樣做;如果不是,就做另一些事情”。對於這種基本的程式設計方法,下一章會詳細說明在Java裡是如何實現的。

2.11 練習

(1) 參照本章的第一個例子,建立一個“Hello,World”程式,在螢幕上簡單地顯示這句話。注意在自己的類裡只需一個方法(“main”方法會在程式啟動時執行)。記住要把它設為static形式,並置入自變數列表——即使根本不會用到這個列表。用javac編譯這個程式,再用java執行它。

(2) 寫一個程式,打印出從命令列獲取的三個自變數。

(3) 找出Property.java第二個版本的程式碼,這是一個簡單的註釋文件示例。請對檔案執行javadoc,並在自己的Web瀏覽器裡觀看結果。

(4) 以練習(1)的程式為基礎,向其中加入註釋文件。利用javadoc,將這個註釋文件提取為一個HTML檔案,並用Web瀏覽器觀看。

英文版主頁 | 中文版主頁 | 詳細目錄 | 關於譯者

,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000頓然面如死灰,黯然無語。自責,內疚,痛苦,悲憤,五味雜陳齊齊裹著酸楚湧上心頭0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000。迫於無奈,甘伯父成了鐵原英雄們的送終人;32年後的今天,我們依然要迫於無奈成為4、5連兄弟們的送終人……這是何種滋味?祖國與人民給我們創造的條件不知比我們的父輩強上多少倍,我們所要面對的敵人不知道比我們的父輩所要面對的不知弱上多少倍。作為祖國與人民的守護者,作為光榮的八一軍旗繼任者,我們怎麼能在這樣的條件,以這樣的方式延續著父輩悲愴的光榮傳統?就像老甘哭嚎的,比起我們的父輩,我們這TM打的是啥仗?我們都TM是沒卵的孬種!  央視版水滸中的公孫勝央視版水滸中的公孫勝(14張)宋江攻打高唐州,卻敗於太守高廉的妖法。吳用讓戴宗去薊州尋取公孫勝,李逵也隨同前往。二人在薊州機緣巧合遇到公孫勝的鄰居,得知公孫勝居住在九宮縣二仙山。戴宗趕赴二仙山,讓李逵假意傷害公孫勝的母親,將公孫勝激出相見。但公孫勝卻不肯出山,稱師傅羅真人不肯相放。戴宗苦苦哀告,又去拜見羅真人,請他放公孫下山。[3] 羅真人傳授公孫勝計算機(computer)俗稱電腦,是現代一種用於高速計算的電子計算機器,可以進行數值計算,又可以進行邏輯計算,還具有儲存記憶功能。是能夠按照程式執行,自動、高速處理海量資料的現代化智慧電子裝置。由硬體系統和軟體系統所組成,沒有安裝任何軟體的計算州費城,前美國職業籃球運動員,司職得分後衛/小前鋒(鋒衛搖擺人),綽號“黑曼巴”/“小飛俠”。[1] 1996年第1輪第13位被夏洛特黃蜂隊選中,後來被交易到湖人隊。整個NBA生涯(1996年-2016年)全部效力於NBA洛杉磯湖人隊,是前NBA球員喬·布萊恩特的兒子 [1] 。科比是NBA最好的得分手之一,生涯贏得無數獎項 [1] ,突破、投籃、罰球、三分球他都駕輕就熟,幾乎沒有進攻盲區,單場比賽81分的個人紀錄就有力地證明了這一點。除了瘋狂的得分外,科比的組織能力也很出眾,經常擔任球隊進攻的第一發起人。另外科比還是聯盟中最好的防守人之一,貼身防守非常具有壓迫性。2016年4月14日,科比·布萊恩特在生涯最後一場主場對陣爵士的常規賽後宣佈退役。[1] 2017年12月19日,湖人主場對陣勇士,中場時刻為科比的8號和24號2件球衣舉行了退役儀式。[2] 2018年3月13日,科比憑藉和動畫師格蘭·基恩合作的短片《親愛的籃球》獲得第90屆奧斯卡最佳短片獎。[3] 來越普遍,改革開放以後,中國計算機使用者的數量不斷攀升,應用水平不斷提高,特別是網際網路、通訊、多媒體等領域的應用取得了不錯的成績。1996年至2009 年,計算機使用者數量從原來的630萬增長至6710 萬臺,聯網計算機臺數由原來的2.9萬臺上升至5940萬臺。網際網路使用者已經達到3.16 億,無線網際網路有6.7 億移動使用者,其中手機上網使用者達1.17 億,為全球第一位。五雷天罡正法,讓他下山輔助宋江“保國安民,替天行道”,又送八字真言,命他“逢幽而止,遇汴而還”。公孫勝到高唐州後,與高廉鬥法,以五雷天罡正法破了高廉的妖術。高廉欲要駕雲逃走,結果被公孫勝用法術從雲中打落,最終被雷橫砍死。梁山軍得以攻破高唐州。[10] 大聚義攻打芒碭山時,公孫勝擺下八陣圖,擒獲八臂哪吒項充、飛天大聖在位於費城郊區高中時期的科比高中時期的科比(7張) 的勞爾梅里恩的勞爾梅里恩高中(LowerMerionHifg School),科比憑藉驚人的高中生涯贏得了全美國的認可。作為一個新人,科比就可以在學校(三年級和四年級)籃球隊出任首發。[15] 科比在高中二年級時是由他的父親執教的。儘管在他的第一年球隊很平庸,但在接下來的三年裡科比打滿了所有的5個位置,並率隊取得了77勝13負的紀錄。[15] 在adidasABCD訓練營,科比獲得了1995年高中生MVP獎,並且和後來的隊友拉瑪爾·奧多姆並肩作戰。[16] 在高中時期,時任76人隊主教練約翰·盧卡斯(John Lucas)邀請科比試訓並與球隊一起訓練,在那裡科比與傑裡·斯塔克豪斯進行了一對一比賽。[17] 在他高中四年級時,科比帶領球隊拿到了50年來第一個州級冠軍。高中四年級時,科比場均30.8分,12個籃板,6.5次助攻,4.0次搶斷和3.8次蓋帽,他帶領勞爾梅里恩高中取得31勝3負的戰績。科比高中生涯結束後,超越了威爾特·張伯倫(Wilt Chamberlain)和萊昂·西蒙斯(Lionel Simmons),以2883分打破了賓夕法尼亞州東南地區的高中得分紀錄。[15] [18] 憑藉高中四年級的表現,科比拿到了好幾個獎項,包括奈史密斯年度最佳高中生球員、佳得樂全美年度最佳高中球員、麥當勞全美最佳陣容、今日美國全美第一陣容球員。科比的高中籃球教練格雷格·唐納(Greg Downer)對他的評價是“具有統治力的全能球員”。1996年科比邀請R&B女歌手布蘭蒂·諾伍德(Brandy Norwood)參加了自己的畢業舞會, [19] 儘管他們只是朋友。科比在畢業時學術能力評估考試(SAT)中得到1080分 [20] ,這足以確保他拿到籃球獎學金進入不錯的大學。然而,最終17歲的科比決定直接進入NBA,成為NBA歷史上第6位直接從高中進入NBA選秀的球員。[15] 因為直接從高中進入NBA並不常見(凱文·加內特是20年來唯一的例外),科比的決定得到了很多的關注。[15] 科比曾說過如果高中畢業後去上大學,他將會選擇杜克大學。[21-22] 運動經歷編輯1996年NBA選秀作為科比 1996年轉會洛杉磯湖人隊科比 者隊的系列賽,第二場的第二節比賽中科比扭傷了腳踝,錯過了那場比賽的剩餘時間和第三場比賽。在第四場比賽中,科比在下半場得到22分,帶領球隊在奧尼爾犯滿離場的加時賽中取勝。科比投中了制勝球幫助球隊以120-118領先。[50] 隨著第6場比賽獲勝,湖人隊拿到了自1988年來第一座NBA總冠軍。[51-53] 2000年奪冠後科比與父母的紀念照童年時期1963年2月17日,大學時期大學時期(18張) 邁克爾·喬丹出生在美國紐約布魯克林區,五歲的時候,喬丹一家人便搬到了北卡羅來納州,小時候的喬丹同父親關係很好,喬丹扣籃時著名的吐舌動作就是來源於父親做修理工作時的動作,那時的兩人對棒球很是熱衷。小時候的喬丹非常的淘氣,在跟著哥哥喜歡上籃球后,喬丹業餘時間全都耗在了球場上。[6] 高中時期威爾明頓蘭尼高中喬丹籃球生涯的起點,不過年幼的喬丹並不引人注目,第二年時,他的身高只有5尺11寸,又瘦又小的他被教練從一隊降入二隊。不過喬丹

88a625cdaac1b97f5cdf385aa6bd6ad3.png

  • 掃 碼 加個 人 微 信 哦

  • 歡 迎 大 家 分 享 到 朋 友 圈 哦

  • 網站:http://www.laomn.com

版權宣告:文章源於網路,不代表版主個人觀點,如侵權或者不當之處,請聯絡編輯刪除.

投稿信箱:[email protected](歡迎您原創投稿)

責任編輯:沈丘人(微信:ishenqiu)QQ:714343803

⊙網站:http://www.laomn.com

你若喜歡,別忘了點個27a46e1c2e6dadae9e9e5f86dc0fe4f9.gif