JAVA初學教程進階
Java語言是目前最受歡迎的程序語言之一,與傳統的程序語言相比(比如C、C++),Java語言簡單易學,使用它編程時間短、功能強,人們接受起來也更快、更簡便。Java主要具有以下三個特點:
第一, 跨平臺,不管Windows還是Unix或者其他平臺,它都可以使用;
第二, 面向對象;
第三, 動態域的控制。
1.1 初識Java語言
像其它編程語言一樣,Java編程語言也被用來創建應用程序。那,首先我們還是從一個最普遍的小應用程序範例來切入——在屏幕上顯示字串“Hello World!”。下列代碼給出了這個Java應用程序。
1.1.1 HelloWorldApp
CODE:
[Copy to clipboard]
1.//
2.// Sample HelloWorld application
3.//
4.public class HelloWorldApp{
5.public static void main (String args[]) {
6.System.out.println ("Hello World!");
7.}
8.}
以上程序行是在你的屏幕上打印“Hello World!”所需的最少組件。接下來,我們就針對上面給出的這段程序來簡單解釋一下,並且來實際編譯、運行它。
1.1.2 描述HelloWorldApp
第1-3行
程序中的1-3行是註釋行
1 //
2 // Sample HelloWorld application
3 //
第4行
第4行聲明類名爲HelloWorldApp。類名(Classname)是在源文件中指明的,它可在與源代碼相同的目錄上創建一個 classname.class文件。在本例題中,編譯器創建了一個稱爲HelloWorldApp.class的文件, 它包含了公共類HelloWorldApp的編譯代碼。
4 public class HelloWorldApp{
第5行
第5行是程序執行的起始點。Java技術解釋器必須發現這一嚴格定義的點,否則將拒絕運行程序。
其它程序語言(特別是C和C++)也採用main ()聲明作爲程序執行的起始點。此聲明的不同部分將在本課程的後幾部分介紹。
如果在程序的命令行中給出了任何自變量,它們將被傳遞給main()方法中被稱作args的String數組。在本例題中,未使用自變量。
5 public static void main (String args[]) {
- public-方法main()可被任何程序訪問,包括Java技術解釋器。
- static- 是一個告知編譯器main()是用於類HelloWorldApp中的函數的關鍵字。爲使main()在程序做其它事之前就開始運行,這一關鍵字是必要的。
- void- 表明main()不返回任何信息。這一點是重要的,因爲Java編程語言要進行謹慎的類型檢查,包括檢查調用的方法確實返回了這些方法所聲明的類型。
- String args [] - 是一個String數組的聲明,它將包含位於類名之後的命令行中的自變量。
java HelloWorldApp args[0]args[1]····
第6行
第6行聲明如何使用類名、對象名和方法調用。它使用由System類的out成員引用的PrintStreamout對象的println()方法,將字串“Hello World!”打印到標準輸出上。
6 System.out.println (“Hello World!”);
在這個例子中,println()方法被輸入了一個字串自變量並將其寫在了標準輸出流上。
第7-8行
本程序的7-8行分別是方法main()和類HelloWorldApp的下括號。
7 }
8 }
1.1.3 編譯並運行HelloWorldApp
編譯
當你創建了HelloWorldApp.java源文件後,用下列程序行進行編譯:
c:/student/javac HelloWorldApp.java
如果編譯器未返回任何提示信息,新文件HelloWorldApp.class則被存儲在與源文件相同的目錄中,除非另有指定。
運行
爲運行你的HelloWorldApp應用程序,需使用Java解釋器和位於bin目錄下的java:
c:/student/ java HelloWorldApp
Hello World!
1.1.4 嚴格的約定
通過上面實際編寫、編譯和運行這個簡單的例子,我們會發現Java是一種限制很嚴格的語言。我們在編寫Java程序的時候,一定要嚴格遵從它的約定,以後你會發現這些約定對維護和組織程序,使你養成一種優良的編程風格都很有幫助。
->; 源文件的類型
在Java中,一個源程序文件被稱爲一個編譯單元。它是一個包含一個或多個類定義的文本文件。Java編譯器要求源程序文件必須使用.java文件擴展名。這裏可以注意到這個文件的擴展名是4個字符,所以,你的操作系統必須要有支持長文件名的能力。
->; 源文件的命名
如果.java文件包括一個公共類,那麼它必須使用與那個公共類相同的文件名。例如在前例中的類的定義是
public class HelloWorldapp
源文件名則必須是HelloWorldapp.java
->; 類的數量
在源文件中,可以定義多個類,但每次只能定義一個公共類。
->; 標識符
Java中使用的標識符可以是大寫和小寫字母、數字、下劃線(_)、美元符號($)的任意組合。以下是一些有效的標識符:
Year99 count this_is_ok $some
以下是一些無效的標識符:
99year hello# not/ok
這裏需要提醒大家注意的是,Java是一種大小寫敏感的語言,所以大家在書寫代碼的時候一定要注意大小寫的運用。
1.2 結構與構件
現在,我們從一個典型的Java源文件來了解一下Java程序涉及到的一些重要的構件,以及這些構件的結構。
CODE:
[Copy to clipboard]
1 package trades;
2 import java.util.Vector;
3 public class Quote extends Thread implements Tradable {
4 // Code goes in here
5 }
那我們從上面的例子中可以發現源文件的結構主要包含三個要素:
->; 一個包聲明(可選)
程序的第1行就是聲明瞭一個包(package),把該程序放在這個包中間。
->; 任意數量的包引入語句(可選)
程序的第2行是要求該程序引入系統提供的一個包java.util.Vector。
->; 任意數量的類的聲明
程序的3-5行則是聲明瞭一個public的類Quote,它是從它的超類Thread擴展得到,並且實現Tradable的接口。
該三要素必須以上述順序出現。即,任何包引入語句出現在所有類定義之前;如果使用包聲明,則包聲明必須出現在類和引入語句之前。
結合上面的例子,我們接下來簡單的討論一下涉及到的這些構件,包package、包引入import、類class、方法method和變量variable。
1.2.1 包package
包實際上就是一個組織類class和接口interface的集合。通過包的這種機制,來把類名空間劃分成更多易於管理的塊。這樣做其主要目的就是可以避免類名的衝突,在不同的包裏的類,其名字相同也不會發生衝突。包的主要功能如下:
->; 依照功能來組織和劃分類。例如:java.awt包含了構成抽象窗口工具包(AWT)的類,這個包被用來構建和管理應用程序的圖形用戶界面。
->; 有助於定義變量和方法的訪問控制。
->; 通過這種包和包引入的機制,也可以保持程序的相對獨立性,有利於模塊化程序設計的實現。
聲明包的定義語句必須放在源文件的頂端。如果你沒有顯式的聲明一個包,那麼Java會把你的類放入缺省包(default package)裏面,這個包沒有名字。
Java使用文件系統目錄來存儲包,目錄名必須和包嚴格的匹配。另外,這裏還要簡單談論一下類路徑(CLASSPATH)環境變量的問題。Java編譯器使用參考的包層次的根是由類路徑決定的。例如,你可以在DOS系統環境下使用如下的命令來指定類路徑:
set CLASSPATH=C:/Mysource;C:/Mypackages
如果我們在源文件類的聲明前有以下語句:
Package trades.quotes
那麼,這個源文件就放在下面這個目錄裏面:
c:/Mypackages/trades/quotes
最後,需要提醒的是,如果你定義的類已經指定到了某個包中,那麼在運行的時候你也需要指定相應的包名和類名一起使用。
同學們可以結合實驗二來加深對包概念的理解。
1.2.2 類class
類是面向程序設計中最小的抽象單元,它就像是一個數據和代碼的容器。它也是Java裏面最重要的一個要件。它通過實例化轉變爲對象,在實例化的時候自動調用構造函數來初始化對象。
對於類的聲明比較複雜,它可以使用很多的修飾符,我們以下面的例子來簡單談論一下這些修飾符。
public abstract class Myclass extends Parent implements A,B {}
首先我們看到的public修飾符,是定義的類的訪問控制屬性,這個我們在下一章會有詳盡的介紹。
然後我們看到的abstract修飾符是表示該類是個抽象類,需要其他類來擴展。這裏再介紹一個final修飾符,它與abstract修飾符的意義正好相反,它表示該類不能擴展。所以abstract和final不能在聲明類的時候同時使用。
在Java中所有的類都擴展一個超類,如果我們沒有指定一個超類,那麼系統會把Object類作爲它要擴展的超類,Object類就是所有類的超類。這裏需要注意的是,在C++中我們使用基類(base class)和繼承類(derived class)的稱謂,而在Java中我們一般稱爲超類(super class)和子類(subclass)。
另外,需要提一下的是一個特殊的關鍵字this,它用來引用正在被調用方法的所屬當前對象。
1.2.3 接口interface
接口是一個非功能性、抽象的類,它包含常量和沒有功能性的方法聲明。也就是說,用interface,你可以指定一個類必須做什麼,而不是規定它如何去做。接口在語句的構成上與類十分相似,但是它們缺少實例變量,而且它們定義的方法是不含有方法體的。
接口中聲明的變量,一般是final和static型的,意思是它們的值不能通過實現類而改變,也就是說它們被看作是常量,而且它們還必須以常量值初始化。
對於接口來說,它們定義以後都是需要類來實現implement的。也就是說,使用具體的類來實現上面的“如何做”。一個類可以實現多個接口,一個接口也可以被多個類來實現。
另外,接口也可以擴展其他接口來實現繼承。如:
interface MyInterface extends YourInterface, Runnable {}
1.2.4 方法method
方法聲明的是被調用執行的代碼,它可以使用傳遞的參數並且返回一定類型的返回值。對於方法的修飾符也比較複雜和繁多。我們仍然以一個例子來簡單談論以下其中的一些修飾符。
public static final synchronized double getPrice ( final int itemCode, Color itemColor ) throw Exception { /* code here */}
首先,Public是定義的方法的訪問控制屬性,這個我們在下一章會有詳細介紹。
然後,static、final和synchronized是特殊的修飾符。同樣需要注意的是其中final和abstract修飾符不能同時使用的。
最後,我們可以看到該方法getPrice返回一個double數據類型的返回值,而且裏面定義了兩個參數(itemCode和itemColor)。
另外,我們還注意它通過throw修飾符,表示它會拋出一個Exception的異常,關於異常我們在後面的章節會介紹到。
接下來我們會介紹兩種比較特殊的方法。
->; Main方法
Main()方法是Java程序的入口起點,它和其他方法的定義類似,只是它包含一個字符串數組用來傳遞命令行方式執行程序時所跟的參數。如下的例子它把命令行方式所跟的參數全部顯示出來:
CODE:
[Copy to clipboard]
public class MainTest {
public static void main ( String [] args ) {
for ( int i = 0 ; i < args.lenth; i++ ) {
System.out.println(“Argument ” + i + “: ” + args[i] );
}
}
}
執行如下:
c:/java project/Main>; java MainTest Philip K Dick
Argumet 0: Philip
Argumet 1: K
Argumet 2: Dick
這裏需要注意的是,如果Main()方法沒有使用static修飾符,那麼編譯不會出錯,但是如果你試圖執行該程序將會報錯,提示main()方法不存在。這是因爲你如果這樣使用命令行的形式直接執行該程序,MainTest類並沒有實例化,所以其main()方法也不會存在,而使用static修飾符則表示該方法是靜態的,不需要實例化即可使用。
->; 構造函數Constructor Method
當類被實例化的時候,第一個被調用的方法就是構造函數。構造函數的主要作用就是初始化變量。如果沒有定義構造函數,那麼Java會使用其超類的默認構造函數。
構造函數與其他方法相比,主要具有以下的特點:
->; 構造函數的名字和其類名相同。
->; 沒有返回值。
->; 構造函數不能像其他超類的方法那樣被繼承。
->; 不能使用final、abstract、synchronized、native或者static修飾符。
有時候,我們在編寫構造函數的時候,可能需要首先調用其超類的構造函數,這裏我們使用super的關鍵字,實際上它同this關鍵字的作用類似,只是它指的是其超類。如下的例子:
CODE:
[Copy to clipboard]
class DataServer extends Server {
public String serverName;
public DataServer ( int startCode ) {
super ( startCode );
serverName = “Customer Service”;
}
}
需要注意的是,調用超類構造函數super()的語句必須放在其構造函數定義的前面,否則編譯器會報錯。
1.2.5 變量variable
變量是Java程序的一個基本存儲單元。變量由一個標識符、類型及一個可選初始值的組合定義。此外,如同定義方法一樣,它也有各種的修飾符。比如訪問控制屬性的修飾符public、private、protected和final、static等。這裏需要注意的是,變量不能使用 synchronized、abstract和native修飾符。
在定義變量的時候需要指明其類型,除了常用的基本類型(比如int型、Boolean型等)以外,也可以使用對象類型。
1.2.6 引入語句import
使用import引入語句是允許你選擇某個包中的某個類或者所有類,使之能在你當前的代碼中能方便的使用。例如:
import java.util.Dictionary; //引入java.util包中的Dictionary類
import javax.swing.*; //引入javax.swing包中的所有的類
當然如果你不使用引入語句也可以使用其他包中的其他的類,只要你指定引用對象的全名。比如:
java.util.Date now = new java.util.Date();
另外,java.lang包是會被自動引入到源程序中的。(待續)
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 1樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2004-5-19 12:13
1.3 關鍵字和標識符
Java語言一共使用了48個保留關鍵字,他們主要可以分爲如下幾類。
->; 訪問控制
private , protected , public
->; 類、方法和變量修飾符
abstract , class , extends , final , implements , interface , native , new , static , strictfp , synchronized , transient , volatile
->; 程序控制語句
break , case , continue , default , do , else , for , if , instanceof , return , switch , while
->; 錯誤處理
catch , finally , throw , throws , try
->; 包相關
import , package
->; 基本類型
boolean , byte , char , double , float , int , long , short
->; 變量引用
super , this , void
->; 未使用的關鍵字
const , goto
這些關鍵字的具體意義可以參考語法書,這裏就不再詳細闡述了。
另外,除了這48個關鍵字以外,還有3個語法保留字,即null、true和false。
1.4 變量的初始化
變量從聲明的位置來看可以分爲兩種類型,一是實例變量instance variable,即聲明在類一級;另一種是局部變量local variable,它聲明在方法一級。這兩類變量除了聲明的位置不同,它們最主要的區別在於是否需要初始化的問題。下面我們具體來討論一下這個問題。
->; 實例變量
類的成員就是定義在類一級的變量。它們實際上是可以不需要初始化的,系統一般會自動給它們賦一個默認值。
->; 基本類型
對於8種基本類型來說,Boolean型默認賦值false,char型會默認爲Unicode字符集的/u0000,而其餘幾種類型都默認爲0。
->; 對象類型
對於對象類型,系統不會賦予任何默認值,但會表示爲null。
->; 數組類型
數組類型於對象類型類似,當你不初始化它的時候,它也是等於null。但如果你初始化它,則有些不同,它與基本類型相似會默認爲0。
->; 局部變量
對於局部變量,一般來說它必須初始化。因爲無論是基本類型還是對象類型,系統都不會自動賦於任何默認值,所以你必須指定一定的值。當然,如果你定義了局部變量而不去使用它,編譯也是可以通過的。
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 2樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2004-5-25 08:53
第二次:修飾符
2.1 訪問控制
封裝將數據和處理數據的代碼連接起來。同時,封裝也提供了另外一個重要屬性:訪問控制。通過封裝你可以控制程序的某個部分可以訪問類的成員,防止對象的濫用,從而保護對象中數據的完整性。對於所有的面向對象的語言,比如C++,訪問控制都是一個很重要的方面。由於Java語言使用了包的概念,使它的訪問控制相對來說更復雜一些。我們把控制訪問控制權限的修飾符主要分爲兩類,類和它的方法及變量,下面我們分別簡單介紹。
-類的訪問控制
->; Default:當類不使用任何訪問控制修飾符時,即採用的默認的訪問控制權限。它允許同一個包內的類訪問,而對於它所在包以外的類則不能訪問。
->; Public:允許任何包中的任何類訪問,對Java裏面的所有類開放。
-方法和變量的訪問控制
->; Public:所有類均可以訪問。
->; Private:只能被它所在的類中的成員訪問,使該定義的成員對外在的類不可見。
->; Protected:可以被同一個包的類訪問,另外其所有子類也可以訪問。
->; Default:當成員不使用任何訪問控制修飾符時,即採用默認的訪問控制權限。它和Protected類似,唯一的區別在於子類訪問權限,它僅允許同一個包的子類訪問,而其他包中的子類則不可以訪問。
2.2 其他修飾符
除了訪問控制修飾符,Java還有其他繁多的修飾符來聲明類、方法和變量,下面分別針對所修飾的對象來簡單介紹一下主要的修飾符。
-類修飾符
->; final:用來指定該類不能被其他類擴展,從而阻止繼承。
->; abstract:表示該類是不允許被實例化的類,也就是說該類需要被擴展繼承。被這樣聲明的類也稱爲抽象類。
顯而易見,final和abstract不能同時使用。
-方法修飾符
->; abstract:被聲明的方法稱爲抽象方法,不含任何代碼,需要其繼承的子類的相應方法覆蓋重載。這裏需要注意的是被聲明有abstract方法的類必須被聲明爲abstract。
->; final:聲明的方法不允許被覆蓋重載。
->; static:聲明的方法被成爲類方法,不依賴於任何的對象,不需要實例化對象即可直接使用類名來調用該方法。注意的是在該方法體內不可訪問實例變量。
->; 變量修飾符
->; static:被聲明爲static的變量實際可以看作就是全局變量,同樣不需要實例化對象即可直接使用類名來引用之。
->; final:被聲明的變量的內容不可以被修改,實際可以被看作是一個常量,類似於C或者C++中的const。
2.3 缺省構造函數
我們都知道當對象被實例化的時候,構造函數總是被調用。如果我們在定義類的時候不指定一個構造函數,Java會自行創建一個不帶參數的缺省構造函數。而如果我們定義有了一個構造函數,則Java不會再創建缺省構造函數。
更值得注意的是,如果子類的超類不含有不帶參數的構造函數,那麼子類在使用缺省構造函數就會出錯,Java不會爲子類創建不帶參數的缺省構造函數。因此,我們在使用缺省構造函數的時候要比較小心。我們可以看如下的例子:
CODE:
[Copy to clipboard]
class Fruit {
public Fruit ( String color ) {
System.out.print ( “color = ” + color ) ;
}
}
class Apple extends Fruit {
public static void main ( String [ ] args ) {
Apple m = new Apple () ;
}
}
運行結果出錯:
Fruit.java:6: No constructor matching Fruit ( ) found in class Fruit .
Class Apple extends Fruit {
1 error
2.4 合法的返回類型
由於在方法調用的時候,方法返回的類型有可能與實際聲明的類型不同,因此我們需要關心什麼樣的返回類型纔是合法的。實際上,系統採用了隱式的類型轉換來處理類型的返回。以下幾種情況的是合法的:
->; 如果聲明的是浮點類型,那麼可返回整型類型。
->; 如果聲明的是整型類型,那麼只要返回的整型類型範圍小於或等於聲明的類型,返回合法。
->; 如果聲明的是對象類型,那麼只要返回的是該對象類型,或者是其子類的對象類型,合法。
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 3樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2004-7-20 16:58
第三次:JAVA運算符
3 運算符
同大多數的編程語言一樣,Java語言也包含了許多的運算符。如果大家學習過C或者C++,會發現下面介紹的各種Java的運算符都與之類似。
3.1.1 賦值運算符 =
這是任何編程語言的最基本的運算符,它用來給變量指定一個值。對於基本類型來說,賦值都便於理解,將新的值賦給變量並保存在變量中供使用。但對於對象類型來說,這裏就有一點區別,特別需要提醒大家注意。
對象類型並不是把實際的值(這裏是實例)賦給了對象類型的變量,而是賦給的一個參考指針。這樣,源對象類型的變量和新的這個變量實際上是指向的同一個實例,如果使用其中一個讓實例改變,那麼相應的另一個所指向的實例也會改變。這裏我們可以借用C裏面的指針的概念來方便理解,但實際上Java是不具有指針的概念和定義的。
我們通過下面的例子可以進一步來理解這個概念。
CODE:
[Copy to clipboard]
import java.awt.Dimension;
class ReferenceTest {
Dimension a = new Dimension ( 5,10 );
System.out.println (“a.height = ” + a.height ) ;
Dimension b = a ;
b.height = 30 ;
System.out,println (“a.height = ” + a.height + “after change to b ”);
}
}
運行結果:
c:/java Project/Reference>;java ReferenceTest
a.height = 10
a. height = 30 afer change to b
另外,賦值運算符還可以和其他的運算符,聯合組成新的賦值符。如*=、/=、+=、-=等等,這於C或者C++類似。
3.1.2 比較運算符
比較運算符是用來對相同數據類型的變量進行大小或者是否相等、相同的比較,返回的是Boolean類型的值。因此也就大概分爲兩類。
n >;、>;=、<、<=
這是比較變量的大小關係,與我們學過的任何編程語言相同,就不再介紹了。
n = = 、! =
這是比較變量是否相等或相同。這對於平常的比較基本類型的變量容易理解,只是我們要強調一下對對象類型的比較。與我們前面介紹的賦值運算符類似的是,它也是進行的對其參考指針的比較,而並不是比較兩個內容上的差別。我們可以藉助下面的例子來理解。
CODE:
[Copy to clipboard]
import java.awt.Button
class CompareRefernce {
public static void main ( String [ ] args ) {
Button a = new Button ( “Exit”);
Button b = new Button ( “Exit”);
Button c = a;
System.out.println ( “Is refernce a = = b ? ” + ( a = = b) ) ;
System.out.println ( “Is refernce a = = c ? ” + ( a = = c) ) ;
}
}
運行結果:
Is refernce a = = b ? false
Is refernce a = = c ? true
3.1.3 instanceof運算符
這個是Java語言特殊的一個運算符,它是用來測試其對象是否屬於某類或其超類。但是這裏需要提醒大家的是,如果你使用instanceof來比較不是一個繼承關係樹上的類,Java能夠編譯通過,但運行的時候會報錯。另外,你可以對null對象使用這個運算符,只是無論對於什麼類測試的結果都是 false。
3.1.4 算術運算符
加+、減-、乘*、除/和取模%運算,這與其他的編程語言類似,不再詳述。
3.1.5 自增++、自減--運算符
Java的自增和自減運算符,與C語言類似,同樣需要注意的是其放置的位置不同,可能的結果也不同。如果放置在變量的前面,表示先自增(減)再參與下步運算,而如果放置在後面則表示先參與運算再自增(減)。如下的例子說明了自增運算符的使用:
CODE:
[Copy to clipboard]
class IncDec{
public static void main ( String [ ] args ) {
int a = 1;
int b = 1;
int c;
int d;
c = ++b;
d = a++;
c++;
System.out.println ( “a = ” + a );
System.out.println ( “b = ” + b );
System.out.println ( “c = ” + c );
System.out.println ( “d = ” + d );
}
}
運行結果:
a = 2
b = 2
c = 3
d = 1
3.1.6 字符串連接運算符 +
Java語言與C語言類似,也使用+作爲連接字符串的運算符,這實際是對String類重載了+運算符。
3.1.7 位運算符
包括位移運算和位邏輯運算,這也與C語言相似。
->; 位移運算
>;>;右移、<<左移、>;>;>;無符號右移。
->; 位邏輯運算
&與、|或、^異或、~非運算,這於其他的編程語言類似,不再詳述。
3.1.8 邏輯運算符
與&&、或||,這於其他的編程語言類似,不再詳述。只是需要提醒大家不要把它們和位邏輯運算符混淆,這也是初學者最容易犯的錯誤。
3.1.9 條件運算符 ?:
這與C語言完全相同,具體不再解釋。
3.1.10 類型轉換
我們在編寫程序的時候經常需要對變量的類型進行轉換,Java語言與其他的編程語言類似,也提供兩種類型轉換方式,即顯式轉換和隱式轉換。轉換的對象可分爲兩類,一是基本類型,二是對象類型。
這裏需要掌握這樣一個要點。對於基本類型來說,凡是大轉小(以類型的寬度考慮)需要使用顯式轉換,也就是需要在變量前面強制給出需要轉換成的類型。而對小轉大來說,系統會自行進行隱式轉換。
對於對象類型來說,也與之類似。凡是超類轉子類則需要使用顯式強制轉換,而子類轉超類系統可自行進行隱式轉換。另外還需要注意的一點是,對於不在一個繼承關係樹上的類要進行強制轉換,Java編譯可通過,但實際運行會出錯。
3.2 equals()方法
equals()方法實際與= =運算符作用相同,也是用來比較相同類型的兩個變量是否相同或相等。只是有點區別的是,對於String類來說,它重載equals()方法,使用它不是比較兩個參考指針的區別,而是實際對所指向的具體內容進行比較,這也滿足了平時我們對比較字符串的實際需求。當然,對其他類來說,你也可以重載 equals()方法,使其滿足你的實際需要,來比較兩個對象類型的變量。
3.3 優先級
與其他編程語言類似的,Java語言的運算符同樣涉及到優先級別的問題,書上130頁從高到低給出了所有運算符的優先級。建議大家,如果對某些運算符之間的優先級不是很清楚的時候,可以使用()來改變它們的優先級關係。
3.4 方法的參數傳遞
最後,簡單討論一下方法的傳遞的問題。Java語言的參數傳遞類型主要可以分爲兩種,值傳遞和引用傳遞。藉助C語言的概念,我們知道,第一種就是把參數值直接複製成方法體的參數,這樣對方法體中的參數的改變不會影響到調用它的參數。而對於第二種,參數的引用(或者說是個指針)被傳遞給了方法體的參數,該引用用來訪問調用中指定的實際參數。這樣,對方法體參數的改變將會影響到調用方法體的參數。
由於沒有指針的概念,Java的參數傳遞相對比較簡單。對於一般的基本類型來說,都採用的是值傳遞;而對於對象類型則是使用的引用傳遞。
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 4樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2006-4-20 10:20 主題:
第四次:JAVA程序控制語句
4.程序控制語句
我們在使用任何編程語言都使用過程序控制語句,Java語言的程序控制語句基本與C語言完全相同,它主要分爲以下幾種:選擇、循環和跳轉。
4.1 選擇語句
4.1.1 if語句
if語句是最基本的條件判斷語句,用於根據條件來控制程序的執行路徑。其完整格式如下:
if (condition) statement1;
else statement2;
if和else的對象statement可以是單個語句,也可以是個程序塊。else子句是可選的。
另外if-else可以嵌套。所以這裏需要提醒大家注意的是,如果你沒有使用{}來保證每個程序塊是具體所屬那個if或者else子句,那麼一定要注意 if和else的匹配關係。一個else子句總是對應着它的同一個塊中的最近的if語句,而且該語句沒有於其他的else語句相關聯。
4.1.2 switch語句
switch語句是Java的多路分支語句。它提供了一種基於一個表達式的值來使程序執行不同部分的簡單方法。它比使用一系列if-else-if語句效率顯得更高,也更方便。其通用格式如下:
switch ( expression ) {
case value1:
// statement sequence
break;
case value2:
// statement sequence
break;
.
.
.
case valueN:
// statement sequence
break;
default:
// default statement sequence
}
表達式expression必須爲byte、short、int或char類型。每個case子句後的值必須是於表達式類型兼容的特定的一個常量(注意必須是常量,而不是變量)。Default子句是可選的。重複的default子句或者重複的case值是不允許的。
4.2 循環語句
4.2.1 while循環
while語句是Java最基本的循環語句。當它的控制表達式爲真的時候,while語句重複執行單個語句或語句塊。通用格式如下:
while ( condition ) {
// body of loop
}
注意的是,如果循環體只有單個語句,可以不使用{}。後面的do-while、for也類似。
同學們可以結合實驗一來加深對while循環的理解。
4.2.2 do-while循環
與while循環類似,只是循環控制表達式是在循環體的尾部進行測試。這意味着即使表達式爲假,循環體也至少要被執行一次。通用格式如下:
do {
// body of loop
} while ( condition ) ;
4.2.3 for循環
for循環是一個功能強大而且形式靈活的結構。通用格式如下:
for ( initialization ; condition ; iteration ) {
// body
}
它與C語言完全相同,按它分爲的三段,for循環執行的過程也可以看作是三步。首先循環啓動時先執行初始化initialization部分,通常這裏是設置循環控制變量值的一個表達式,作爲控制循環的計數器。然後,計算條件condition的值,來判斷是否滿足該表達式,執行循環體。最後執行循環體的反覆部分iteration,一般來說這裏通常是增加或者減少循環控制變量的一個表達式。
需要注意的是,對於initialization和iteration兩個部分而言,可以使用多個變量表達式,中間用逗號隔開。另外,for循環也可以不含任何的部分,這樣做就是一個死循環。總之,對於for循環語句的使用相當的靈活,大家可以在具體的應用中感受到。
4.3 跳轉語句
4.3.1 break語句
break語句有三種作用。首先,可以在switch語句中使用,用來終止一個子句序列,跳出switch語句。另外,它能用來退出一個循環,這種使用與 C語言也完全一致。第三種,它能作爲一種“先進”的goto語句來使用。這是Java的一個特點,我們特別討論一下。
我們知道,對於一個比較優秀的語言來講,都限定使用goto語句。Java語言雖然把goto作爲了保留關鍵字,但並不使用這個語句。它提供了break 語句來擴展的實現它的一些功能。通過使用帶有標籤的break語句,來指定執行從何處重新開始。標籤break語句的通用格式如下:
break label ;
這裏,標籤label是標識代碼塊的標籤。當這種形式的break執行時,控制被傳遞處指定的代碼塊。但需要注意的是,如果一個標籤不在包圍break的塊中定義,你就不能break到該標籤。一般來說,在實際應用中,帶標籤的break語句可以用來跳轉到多重循環體之外。
4.3.2 continue語句
用法與C語言類似,用來強迫一個循環提早反覆。也就是說,你可以使用continue來繼續運行循環,但忽略這次重複剩餘的循環體語句。
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 5樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2006-4-20 10:32 主題:
第五次:異常處理
同大多數的編程語言一樣,Java語言也包含了許多的運算符。如果大家學習過C或者C++,會發現下面介紹的各種Java的運算符都與之類似。
5.1 try-catch-finally
首先我們介紹一下異常的一些基本概念。Java異常是一個描述在代碼段中發生的異常(也就是出錯)情況的對象。當異常情況發生,一個代表該異常的對象被創建並在導致該錯誤的方法中被引發throw。另外,你需要定義一段代碼來處理這一異常,首先它需要捕獲catch被引發的異常。
如果我們不提供任何異常處理程序,那麼異常會被Java運行時系統的默認處理程序捕獲。任何不是被你程序捕獲的異常最終都會被該默認處理程序處理。默認處理程序會顯示一個描述異常的字符串,打印異常發生處的堆棧軌跡並終止程序。
堆棧軌跡實際顯示了導致錯誤產生的方法調用序列。Java在運行的時候會維護一個堆棧來保存程序運行調用的方法序列。實際上,異常發生以後就是按照這個堆棧的方法序列依次呈遞給這些方法,如果這些方法裏面有異常處理程序就可以捕獲它加以處理,否則會一直呈遞到系統默認的處理程序。
我們通過下面的例子能更容易理解這個調用方法堆棧和異常的呈遞機制。
CODE:
[Copy to clipboard]
Class Exc {
static void subroutine () {
int d = 0 ;
int a = 10 / d ;
}
public static void main ( String [ ] args ) {
Exc.subroutine ();
}
}
運行結果:
java.lang.ArithmeticException: / by zero
at Exc.subroutine(Exc.java:4)
at Exc.main(Exc.java:7)
儘管由Java運行時系統提供的默認異常處理程序對程序的調試很有用,但通常還是需要自己來處理異常。因爲,這樣做一可以修正錯誤,二來可以防止程序的自動終止。
接下來,我們來看一下異常處理塊的通用格式:
try {
// block of code to monitor for errors
}
catch ( ExceptionType1 exOb ) {
// exception handler for ExceptionType1
}
catch ( ExceptionType2 exOb ) {
// exception handler for ExceptionType2
}
// …
finally {
// block of code to be executed before try block ends
}
☆ try子句
用來監控可能產生錯誤的代碼
☆ catch子句
用來捕獲你指定的異常類型,並進行錯誤處理。它必須緊跟try塊,並且可以定義多個catch塊。
☆ finally子句
用來處理善後清理的工作,因爲無論異常是否引發,它裏面的代碼都會執行,甚至你在try塊中定義了return子句,它也一樣會被執行。這是可選的。
5.2 Exception類
前面我們討論的所有異常都來自於Exception類。
在Java編程語言中,異常類可以大致分爲三種。Java.lang.Throwable類充當所有對象的父類。它有Error和Exception兩個基本子類,如下圖所示:
Throwable類不能使用,而使用子類異常中的一個來描述任何特殊異常。
☆ Error表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。
☆ RuntimeException表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。比如,如果數組索引擴展不超出數組界限,那麼,ArrayIndexOutOfBoundsException異常從不會拋出。比如,這也適用於取消引用一個空值對象變量。因爲一個正確設計和實現的程序從不出現這種異常,通常對它不做處理。這會導致一個運行時信息,應確保能採取措施更正問題,而不是將它藏到誰也不注意的地方。
☆ 其它異常表示一種運行時的困難,它通常由環境效果引起,可以進行處理。例子包括文件未找到或無效URL異常(用戶打了一個錯誤的URL),如果用戶誤打了什麼東西,兩者都容易出現。這兩者都可能因爲用戶錯誤而出現,這就鼓勵程序員去處理它們。
在捕獲異常的時候,一定要注意異常類型的匹配。只有catch塊中定義的捕獲異常的類型匹配引發的異常的類型或者其超類,才捕獲並處理。所以,一定要注意你處理的異常類型的繼承關係。另外,對於多個catch塊來說,如果你定義的帶捕獲處理的異常有子類和相應的其超類,一定要注意放置的順序,捕獲超類的 catch塊一定要放置捕獲其子類的catch塊後面。
5.3 throws子句
如果一個方法可以導致一個異常但不處理它,它必須指定這種行爲以使方法的調用者可以保護它們自己而不發生異常。你可以在方法聲明中使用throws子句來實現這一目的。一個throws子句列舉了一個方法可能引發的所有異常類型。這對於除了Error或者RuntimeException及它們的子類以外類型的所有異常是必要的。一個方法可以引發的所有其他類型的異常必須在throws子句中聲明。
針對上面的情況,這裏簡單介紹一下異常的檢查類型的概念。RuntimeException異常類及其子類就是非檢查類型,Error類雖然不屬於 Exception類也是非檢查類型的。對於非檢查類型的異常,即使你在方法聲明中沒有指定它爲可能引發的異常類型,它也會自動正確的被引發,系統保證它們的運行而不會出錯。而除此以外的其他異常類型都是檢查的,也就是如果你要引發它就必須在方法聲明中指定,而且還必須使用catch塊來捕獲處理。
另外,對於throws子句還需要提一下的是其方法的重載問題。對於子類重載超類方法的這種覆蓋重載override來說,要注意子類方法所引發的異常不能比超類的多,你引發的異常類型可以是超類引發異常類型的子類或者根本不引發任何異常,反正不可以超出其超類的範圍。
5.4 引發和創建自定義異常
5.4.1 throw子句
前面我們都是獲取的Java運行時系統引發的異常,然而,我們也可以在程序中用throw語句來引發明確的異常。Throw子句通用格式如下:
throw ThrowableInstance ;
ThrowableInstance一定是Throwable類類型或者其子類的一個對象,所以這裏又涉及到了一個實例化異常類的問題。可以使用new來實例化異常類,需要注意的是,異常的有兩個構造函數:一個沒有參數,一個帶有一個字符串參數。使用後者時,參數指定的是一個描述異常的字符串。如下:
throw new NullpointerException (“demo”) ;
5.4.2 創建自定義異常類
儘管Java內置異常可以處理大多數常見錯誤,你還是可以建立你自己的異常類型來滿足你的特殊要求。建立的方法很簡單,只要定義一個Exception 的一個子類就可以了。
[ 本帖最後由 貓小 於 2006-4-20 10:35 編輯 ]
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 6樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2006-4-20 10:40 主題:
第六次 垃圾回收機制
這裏討論Java的垃圾回收機制,也就是Java管理使用內存的機制。當對象在內存中創建以後,如果你的程序使用完畢了該對象,通常都應該回收這個對象所佔用的內存空間。在C 和C++語言中,一般都靠程序員在代碼中手工編寫代碼來處理這個過程。而Java語言則通過它的JVM(Java虛擬機)使用一種稱作mark- sweep的垃圾回收機制來自動處理這一過程。
6.1 垃圾回收機制
內存空間是計算機最基本、最重要的資源。對內存空間的耗費最主要的就是創建對象。當我們不再需要使用創建的對象時,就需要釋放分配給對象的內存,回收資源。Java使用一種稱爲“堆heap”的結構來管理內存,它使用垃圾回收機制來保證始終有足夠的內存分配給創建的對象。這一內存管理機制通常是系統自動進行,不受程序員干預的。這也就減輕了程序員的工作負擔。
在回收內存空間中,系統主要使用一種稱作標記-清理(mark-sweep)的機制。首先,系統遍歷所有對象的引用指針,如果發現有對象沒有被引用,那麼就把它標記爲未使用。然後,系統把所有的凡是標記了未使用狀態的對象進行清理回收。即使是對於那種兩個未使用的對象互相引用的情況,系統通過的遍歷算法也可以發現,所以這一機制是十分有效的。
另外需要注意的是,回收處理是週期性的運行,它由系統自行控制。它可能延遲任意長的時間來運行回收器,也可能在任意時候運行。所以這就可能在運行的時候出現一些問題,比如程序會暫停或者運行速度減慢。
針對這樣的回收機制,我們在程序中可以顯式的使用一些方法來告訴系統回收我們不需要的對象,提高回收執行的效率。比如,把不再需要使用的對象置爲null,或者賦給其他對象類型變量,使其不引用指向原對象。
6.2 手工干預回收
對於回收機制,都是由系統自行完成,通常我們並不需要關心。但有時候也可以使用一些手段來手工干預內存空間的回收。
Java提供一個java.lang包中的Runtime類來做這樣的工作。我們使用Runtime類的gc()方法來運行垃圾回收器,強制內存空間回收。需要注意的是使用這個方法只是給系統發出一個要求,而不是命令,所以並不能保證一定完成你指定的工作,達到你滿意的效果。 另外還需要注意的是Runtime類沒有構造函數,你需要使用其getRuntime()來實例化它。
有時候當撤消一個對象的時候,需要完成一些操作,來回收一些非Java的資源。對處理這樣的情況,Java提供了一種被稱爲收尾(finalization)的機制,你可以採用與C語言類似的方式來手工回收一些資源。
要實現這一機制,只需要在你需要回收的類中定義finalize()方法即可。Java回收該類的一個對象時就會調用這個方法。在finalize()方法中你需要指定一個對象被撤消前必須執行的操作。
finalize()方法的通用格式如下:
protected void finalize ()
{
// finalization code here
}
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 7樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2006-4-20 10:48 主題:
第七次 重載
重載對於面向對象編程來說是一個難點,相對C++來說,Java這個方面較爲簡單。這裏我們主要討論方法的兩種形式的重載和構造函數的重載。通過本次學習,大家會對Java面向對象編程的思想有更一步的理解。
7.1 方法的重載
通過方法重載可以實現多態,多態性是面向對象編程的一個重要的特點。Java語言中對方法的重載分爲兩類,我們在下面依次具體介紹。
7.1.1 Overload名稱重載
指同一個類中的多個方法可以享用相同的名字,只要它們聲明的參數不同。這種不同體現在或者參數的個數不同,或者其參數類型不同。編譯器根據參數的個數和類型來決定當前所使用的方法。需要注意的是多個方法必須返回相同的數據類型,它們的不同只在於參數。
我們可以通過如下的例子來了解名稱重載。
CODE:
[Copy to clipboard]
public class Mytest {
public void printNumbers ( int a, int b ) {
System.out.println(a);
System.out.println(b);
}
public void printNumbers ( int a, int b, int c ) {
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
7.1.2 Override覆蓋重載
在類層次結構中,如果子類中的一個方法與它超類中的方法用相同的方法名、返回類型和參數表,就稱子類中的方法覆蓋重載超類中的方法。從子類中調用重載方法時,它總是引用子類定義的方法,而超類中定義的方法將被隱藏。也就是說,通過覆蓋重載,子類修改了從超類繼承下來的行爲。
需要注意的是方法覆蓋僅載兩個方法的名稱和類型都相同時才發生。如果僅有名稱相同,那兩個方法只是覆蓋。
另外使用方法覆蓋還需要注意要保證以下幾點:
☆ 覆蓋方法的返回類型必須與它所覆蓋的方法相同。
☆ 覆蓋方法不能比它所覆蓋的方法訪問控制範圍差。
☆ 覆蓋方法不能比它所覆蓋的方法拋出更多的異常。
☆ synchronized修飾符對超類和子類的作用是獨立的。
我們可以通過如下的例子來了解覆蓋重載。
Myparent.java
CODE:
[Copy to clipboard]
public class Myparent {
public void printClassName () {
System.out.println ( “Myparent” );
}
}
Mychild.java
CODE:
[Copy to clipboard]
public class Mychild {
public void printClassName () {
System.out.println ( “Mychild” );
}
}
7.2 構造函數的重載
構造函數和其他的方法一樣也可以被重載,由於它的特殊性,所以它的重載也與其他的方法重載有些不同。主要包括以下幾個方面。
☆ 使用this調用自身的其餘構造函數實現構造函數的名稱覆蓋。如下的示例:
CODE:
[Copy to clipboard]
public class Myclass {
String title ;
//Calling constructor
public Myclass () {
this ( “Default Title ” );
}
//Called constructor
public Myclass ( String t ) {
title = t ;
}
}
☆ 使用super調用超類的構造函數。需要注意的是,如果不顯式的使用super調用超類的構造函數,系統會調用超類的不帶參數的缺省構造函數。另外要使用this()或者super()則必須把它放在其構造函數的首行。如下的示例:
CODE:
[Copy to clipboard]
public class MySuper {
//first constructor
public MySuper () {
System.out.println (“Super1”) ;
}
//second constructor
public MySuper ( String title ) {
System.out.println (“Super2”) ;
}
}
public class MySub extends MySuper {
//first constructor
public MySub () {
super(“the title”)
System.out.println (“Sub1”) ;
}
//second constructor
public MySub ( String title ) {
System.out.println (“Sub2”) ;
}
}
7.3 所屬Is和擁有Has關係
這裏主要是提醒大家明白了一個我們在平時程序設計中經常混淆的概念,即所屬Is和擁有Has關係的概念和區別。我們需要注意的是隻有對於所屬的這種關係,我們纔可以使用子類和超類的程序設計思想。
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 8樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2006-4-20 10:51 主題:
第八次 內部類
內部類就是定義在其他類、方法、甚至表達式中的類,它的特點與一般的類並沒有什麼大的不同。Java語言有四種類型的內部類,下面分別介紹。
8.1 靜態Static內部類
靜態內部類是定義在類內部的類,所以也稱爲嵌套類,並且使用static修飾符來聲明。需要注意的是凡是內部類,其名字都不能和封裝它的類名字相同。對於靜態內部類來說,它只能訪問其封裝類中的靜態成員(包括方法和變量)。
靜態內部類示例如下:
CODE:
[Copy to clipboard]
package mypackage;
public class EnclosiongClass {
private static int staticvar = 0;
public int instancevar = 0 ;
public static class StaticInnerClass {
}
}
8.2 成員Member內部類
成員內部類與靜態內部類相似,也是定義在類內部這一級,只是它不使用static修飾符來聲明。所以它和類中的其他實例變量一樣,都可以看作是其封裝類中的成員。它可以訪問其封裝類中的任何成員。需要注意的是,在成員內部類中不能定義有static變量,但是可以使用局部變量。
由於成員內部類是非static的,所以在創建內部類的實例時,必須有一個其封裝類的實例引用。可見下面的例子:
CODE:
[Copy to clipboard]
public class EnclosingClass {
private int instVar = 1;
public class MemberClass {
public void innerMethod {
// it is okay to do something with instVar here
}
}
public MemberClass createMember () {
return this.new MemberClass ();
}
}
這裏是在封裝類內部創建內部類的實例,實際這個this可以不顯式使用,系統會自行隱式使用來引用封裝類的實例。如果對於在封裝類外部來創建內部類的實例,依然必須要有一個封裝類的實例引用。其語法有兩種,可分別見下面的兩個示例:
EnclosingClass ec = new EnclosingClass ();
EnclosingClass.MemberClass mc = ec.new MemberClass();
或者
EnclosingClass.MemberClass mc = new EnclosingClass ().new MemberClass ();
另外還需要提一下的是this和super在內部類中使用所代表的意義,this是指的該內部類的實例引用,而super是指的其封裝類的實例引用。所以大家在使用這兩個關鍵字的時候一定要注意它所處的位置。
8.3 局部Local內部類
局部內部類是定義在方法體或更小的語句塊中的類。它的使用如同方法體中的局部變量,所以你不可以爲它聲明訪問控制修飾符。同成員內部類相同,也不可以含有 static成員。這裏需要注意的是,在局部內部類和後面將介紹的匿名內部類中可以引用方法中聲明的變量,但這些變量必須是final的。
8.4 匿名Anonymous內部類
在某些時候,你可能需要定義一個類,但在程序中卻從來不會定義它的對象,只是用來把這個類的對作爲自變量直接傳遞給方法,這時就使用匿名類。如下的例子:
pickButton.AddActionListener ( new ActionListener ( )
{
//Code to define the class that implements
//the ActionListener interface
}
)
匿名類總是用來擴展一個現有的類,或者實現一個接口。它沒有名字,所以也沒有構造函數,並且也沒有任何修飾符來聲明它。
一般來說,匿名類經常用於AWT和Swing中的事件處理。
__________________________________
~M.Meng's Cabin
Before posting did you try:
[ J2SE Javadocs | J2EE Javadocs | Google ]
返回頁首 9樓
Unix體驗中心開通Fedora服務器 | 金牌ULP專家課程,5萬年薪就業! | IBM端到端安全解決方案與專業服務 | Wiki、Wiki,快點!
貓小 美女 愛心使者
榮譽版主-大天使
會員UID:38083
註冊時間:2003-1-6 15:57
最後登錄:2007-5-24 19:49
帖子總數: 2272
精華帖子: 20
積分:355
來自:火星人在地球
在線狀態:...離線...
[會員資料] [站內短信] [Blog]
發表於: 2006-4-20 10:56 主題:
第九次 線程
Java語言中一個十分重要的特點就是支持多線程編程。多線程程序包含兩條或兩條以上併發運行的部分。程序中每個這樣的部分都叫做一個線程thread,每個線程都有獨立的執行路徑。因此,多線程是多任務處理的一個特殊形式。
9.1 創建進程
通常,通過實例化一個Thread對象來創建一個線程,Java對此定義了兩種方式。下面我們分別介紹一下。
☆ 實現Runnable接口
創建線程的最簡單的方法是創建一個實現Runnable接口的類。創建過程大致分以下的幾步。
首先,你通過實現Runnable接口的run()方法來創建每一個對象的線程。run()方法能夠像主線程那樣調用其他方法,引用其他類,聲明變量。唯一不同的是,run()在程序中確定另一個併發的線程執行入口。當run()方法返回時,該線程即結束。
其次,你要在你創建的實現Runnable接口的類中,實例化一個Thread類的對象。
最後,實例化了Thread類創建了一個線程後,線程並沒有運行。你要運行你創建的這個線程還要調用它的start()方法。實際上,start()執行的就是一個對run()的調用。
☆ 擴展Thread類
創建線程的另一個方法是創建一個新類來擴展繼承Thread類,然後再創建這個類的實例。當這個子類繼承Thread類時,它必須重載run()方法,這個run()方法就是新線程的入口。另外它同樣也必須調用start()方法去啓動新線程的執行。
9.2 線程的同步
當兩個或兩個以上的線程需要共享資源,它們需要某種方法來確定資源在某一時刻僅被一個線程佔用。這個過程就成爲同步(synchronization)。
與其他語言不同的是,Java提供了一種語言上對同步的支持,極大的簡化了管理線程同步的複雜性。有兩種方法來同步化代碼,兩者都包括了synchronized關鍵字的運用,下面分別說明。
☆ 使用同步方法
在多線程的情況下,你如果有一個或多個方法操縱對象的內部狀態,都必須使用synchronized關鍵字來聲明方法爲同步方法,防止狀態出現競爭。一旦線程進入實例的同步方法,就沒有其他線程可以進入相同實例的同步方法。
☆ 使用同步語句
當我們在類的定義中沒有用到同步方法的時候,你可能也需要對一些操縱對象內部狀態的代碼同步化。這時你可以使用synchronized來聲明一個同步語句塊。
下面給出了synchronized語句的普通格式:
synchronized(object) {
// statement to be synchronized
}
9.3 線程間通信
對於多線程的管理,一般採用一種輪詢的方式。輪詢通常由重複監測條件的循環實現。一旦條件成立,就採用適當的動作。這種方式相對簡單,但卻很大程度上浪費了CPU的時間。Java語言則採用了另外一種機制,避免了輪詢。它通過wait()、notify()和notifyAll()方法實現一個進程間通信機制。這些方法是在Object類中用final聲明定義了的,所以所有的類都包含它們。它們的意義分別如下:
☆ wait():通知被調用的線程放棄管程進入睡眠直到其他線程進入相同管程並調用notify()把它喚醒。
☆ notify():恢復相同對象中第一個調用wait()的線程。
☆ notifyAll():恢復相同對象中所有調用wait()的線程。
這裏需要提醒的是,這三個方法僅在synchronized方法中才能被調用。
9.4 死鎖
這裏,我們介紹一個死鎖的概念。這是我們需要避免在多任務處理中出現的情況。
死鎖發生在當兩個線程對一對有依賴循環時。例如,假設一個線程進入了對象A的管程而另一個線程則進入了對象B的管程。如果A的線程試圖調用Y的同步方法,它將被鎖定。這時,如果B的線程希望調用A的一些同步方法,線程就會永遠等待。系統陷入死鎖的情況。因爲爲到達A,B必須釋放自己的鎖定以使第一個線程可以完成。
9.5 優先級問題
線程優先級被線程調度用來判斷何時每個線程允許運行。理論上,優先級高的線程比優先級低的線程獲得更多的CPU時間。但實際上,線程獲得CPU時間通常由包括優先級在內的多個因素決定的。
我們可以使用setPriority()方法來設置線程的優先級,該方法是Thread類的成員。它的通常格式如下:
final void setPriority(int level)
level指定了對調用線程的新的優先級的設置。Level的值必須在MIN_PRIORITY 到MAX_PRIORITY之間。通常它們的值是1和10。如果要指定默認的優先級使用NORM_PRIORITY,通常值爲5。
另外你還可以使用getPriority()方法來獲得當前的優先級設置。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.