這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)如何實(shí)現(xiàn)J2SE入門,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的呼瑪網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
J2SE入門:
1. 預(yù)備知識(shí)
2. 存儲(chǔ)方式和操作控制
3. 面向?qū)ο蠹夹g(shù)
4. 常用數(shù)據(jù)結(jié)構(gòu)
5. 異常處理機(jī)制
6. 圖像處理和音頻操作
7. 圖形化界面(swing)
8. 多線程技術(shù)
9. I/O操作
10. 基本網(wǎng)絡(luò)技術(shù)
預(yù)備知識(shí):
㈠Java的歷史背景不用多說了
㈡環(huán)境變量設(shè)置及原理
開發(fā)Java程序的第一步必須設(shè)置環(huán)境變量,它主要包括PATH和CLASSPATH的設(shè)置,理解PATH和CLASSPATH的作用對(duì)于Java程序的運(yùn)行是有一定好處的。
PATH:操作系統(tǒng)執(zhí)行某一命令時(shí)都會(huì)通過PATH進(jìn)行搜索;如果將Java的一些工具諸如Java、Javac、Javadoc等的路徑也加入PATH,則當(dāng)運(yùn)行Java的編譯器或解釋器時(shí)系統(tǒng)就可以搜索到這些工具并執(zhí)行操作,這些工具都在jdk目錄下的bin目錄下。
PATH的設(shè)置如下(設(shè)jdk裝在C:j2sdk1.4.2):
PATH=%PATH%;C:j2sdk1.4.2bin;
注:%PATH%表示將原來的PATH路徑保留,也可不設(shè)此項(xiàng)而直接將jdk路徑加到原PATH路徑下。;為Windows下的分隔符(Linux下為:)。
CLASSPATH:為一個(gè)路徑列表,用于搜索Java編譯或者運(yùn)行時(shí)需要用到的類。虛擬機(jī)按以下順序搜索并裝載所有需要的類:
引導(dǎo)類: 組成 java 平臺(tái)的類, 包含 rt.jar 和 i18n.jar 中的類.
擴(kuò)展類: 使用 java 擴(kuò)展機(jī)制的類, 都是位于擴(kuò)展目錄($JAVA_HOME/jre/lib/ext)中的 .jar 檔案包.
用戶類: 開發(fā)者定義的類或者沒有使用 java 擴(kuò)展機(jī)制的第三方產(chǎn)品.
CLASSPATH的設(shè)置如下:
CLASSPATH=.;C:j2sdk1.4.2libtools.jar; C:j2sdk1.4.2_05jrelibrt.jar
注:.表示當(dāng)前目錄,如果覺得這個(gè)目錄名太繁瑣,可以先設(shè)一個(gè)JAVA_HOME,并令JAVA_HOME=C:j2sdk1.4.2,然后再設(shè)CLASSPATH的格式為:%JAVA_HOME%libtools.jar等就可以了。dt.jar是關(guān)于運(yùn)行環(huán)境的類庫,tools.jar是關(guān)于一些工具的類庫
注意事項(xiàng):
程序與類
Java源程序中只能有一個(gè)public類,但可以有任意個(gè)普通類,且此程序文件名必須與public類的類名相同。
包操作
一般為方便管理都將Java的類各自作成一個(gè)文件,再放入一個(gè)Package中,即一個(gè)包中包含若干類包括主類和普通類。運(yùn)行編譯后的程序格式為:
java 包名.主類名
編碼習(xí)慣
Java開發(fā)過程中一定要養(yǎng)成良好的編碼習(xí)慣(要從娃娃抓起^_^),如編寫見文識(shí)義的標(biāo)識(shí)符、代碼縮進(jìn)格式、標(biāo)準(zhǔn)而詳細(xì)的注釋等等。
--------------------------------------------------------------------------------
存儲(chǔ)方式和操作控制
所謂的存儲(chǔ)方式和操作控制其實(shí)就是數(shù)據(jù)結(jié)構(gòu)的選擇和算法的設(shè)計(jì)。程序?qū)懚嗔诉@方面的能力自然能慢慢提高。
㈠存儲(chǔ)方式指的是Java的數(shù)據(jù)類型,在程序設(shè)計(jì)時(shí)變量的選擇也是很重要的,在符合要求的情況下應(yīng)盡量考慮性能。
簡單數(shù)據(jù)類型包括:
整數(shù)類型(Integer):byte, short, int, long
浮點(diǎn)類型(Floating):float,double
字符類型(Textual):char
布爾類型(Logical):boolean
復(fù)合數(shù)據(jù)類型包括:
字符串類型:String
數(shù)組
class
interface
㈡操作方法主要是指程序設(shè)計(jì)中經(jīng)常用到的順序、轉(zhuǎn)移、循環(huán)等控制語句。無論再復(fù)雜的程序,都離不開這些控制語句。因此熟練掌握這些語句的運(yùn)用,才能寫出優(yōu)美而高效的代碼。
順序執(zhí)行
條件轉(zhuǎn)移
Ⅰ if(exp) {
}else(exp) {
}
Ⅱ switch(exp) {
case ? : break;
case ? : break;
…….
default : break;
}
循環(huán)操作
Ⅰ for( ; ; ) {
}
Ⅱ while(exp) {
}
跳轉(zhuǎn)指令
Ⅰ break;
Ⅱ continue;
Ⅲ return;
注:
在操作中有些技巧可以采用:如在循環(huán)操作時(shí)可將判斷結(jié)束條件設(shè)為死循環(huán)的類型(如while(true)),再在程序段內(nèi)部設(shè)置條件break。
break與continue的區(qū)別:break語句是跳出它所指定的塊,不再進(jìn)行終止條件的判斷,并從緊跟該塊的第一條語句處執(zhí)行;continue語句用來結(jié)束本次循環(huán),跳過循環(huán)體中下面尚未執(zhí)行的語句,接著進(jìn)行終止條件的判斷,以決定是否繼續(xù)循環(huán)。
--------------------------------------------------------------------------------
面向?qū)ο蠹夹g(shù)
OO是一門高深的思想,也是現(xiàn)代軟件設(shè)計(jì)的常用思想。OO中有許多前人總結(jié)的原則,應(yīng)該盡量借鑒。比如優(yōu)先使用類聚合而非繼承、針對(duì)接口編程、力求松耦合高內(nèi)聚等等。《設(shè)計(jì)模式精解》一書中的第一章對(duì)于OO和設(shè)計(jì)模式入門非常不錯(cuò),講得深入淺出。一般OO和設(shè)計(jì)模式配合進(jìn)行軟件設(shè)計(jì)能夠發(fā)揮令人出乎意料的效果,所以力薦OO和設(shè)計(jì)模式一起學(xué),在此再介紹一本設(shè)計(jì)模式的圣經(jīng)《設(shè)計(jì)模式--可復(fù)用面向?qū)ο筌浖幕A(chǔ)》(雖然是用C++實(shí)現(xiàn)的,不過思想與語言無關(guān)),書中所介紹的23種模式是對(duì)以往軟件開發(fā)中的一些解決方案的精煉萃取,讓人耳目一新,值得一讀。
㈠OO基本思想是使用類、對(duì)象、繼承、封裝、消息等基本概念來進(jìn)行程序設(shè)計(jì)。
基本特性為封裝性、繼承性、多態(tài)性:
封裝性:將對(duì)象的屬性和操作結(jié)合成一個(gè)實(shí)體,對(duì)外盡量隱藏內(nèi)部細(xì)節(jié),只對(duì)類用戶提供接口。基本原則是不對(duì)外提供public的成員變量,而利用bean的特點(diǎn)提供存取成員變量的set、get方法。
繼承性:可以不太準(zhǔn)確地歸結(jié)為父類擁有共性,子類擁有特性,如客輪是輪船和客運(yùn)工具的特殊類,輪船是父類,客輪是實(shí)現(xiàn)客運(yùn)功能的子類。
多態(tài)性:對(duì)象的多態(tài)性是指在一般類中定義的屬性或服務(wù)被特殊類繼承之后,可以具有不同的數(shù)據(jù)類型或表現(xiàn)出不同的行為。如:"幾何圖形"的"繪圖"方法,"橢圓"和"多邊形"都是"幾何圖"的子類,其"繪圖"方法功能不同。
㈡關(guān)鍵性技術(shù):
類、對(duì)象
類和對(duì)象的關(guān)系就像模具和鑄件的關(guān)系。
類聲明:
[public][abstract|final] class className [extends superclassName]
[implements interfaceNameList] {
成員變量;
成員方法;
}
成員變量:
[public | protected | private ] [static]
[final] [transient] [volatile] type variableName;
變量聲明中限定詞的含義:
static: 靜態(tài)變量(類變量);相對(duì)于實(shí)例變量
final: 常量
transient: 暫時(shí)性變量,用于對(duì)象存檔
volatile: 貢獻(xiàn)變量,用于并發(fā)線程的共享
成員方法:
[public | protected | private ] [static]
[final | abstract] [native] [synchronized]
returnType methodName([paramList]) [throws exceptionList] {statements}
方法聲明中的限定詞的含義:
static: 類方法,可通過類名直接調(diào)用
abstract: 抽象方法,沒有方法體,由子類實(shí)現(xiàn)
final: 方法不能被重寫
native: 集成其它語言的代碼
synchronized: 控制多個(gè)并發(fā)線程的訪問
類中的限定詞:
private
類中限定為private的成員,只能被這個(gè)類本身訪問。如果一個(gè)類的構(gòu)造方法聲明為private,則其它類不能生成該類的一個(gè)實(shí)例。
Default
類中不加任何訪問權(quán)限限定的成員屬于缺省的(default)訪問狀態(tài),可以被這個(gè)類本身和同一個(gè)包中的類所訪問。
protected
類中限定為protected的成員,可以被這個(gè)類本身、它的子類(包括同一個(gè)包中以及不同包中的子類)和同一個(gè)包中的所有其他的類訪問。
public
類中限定為public的成員,可以被所有的類訪問
構(gòu)造方法:
構(gòu)造方法是一個(gè)特殊的方法。Java 中的每個(gè)類都有構(gòu)造方法,用來初始化該類的一個(gè)對(duì)象。構(gòu)造方法具有和類名相同的名稱,而且不返回任何數(shù)據(jù)類型。
重載經(jīng)常用于構(gòu)造方法。構(gòu)造方法只能由new運(yùn)算符調(diào)用。
方法重載和方法重寫:
方法重載是指多個(gè)方法享有相同的名字,但是這些方法的參數(shù)必須不同,或者是參數(shù)的個(gè)數(shù)不同,或者是參數(shù)類型不同。返回類型不能用來區(qū)分重載的方法。
方法重寫是指具有繼承關(guān)系的父子類的方法享有相同名字,子類中重寫的方法和父類中被重寫的方法要具有相同的名字,相同的參數(shù)表和相同的返回類型,只是函數(shù)體不同。java運(yùn)行時(shí)系統(tǒng)根據(jù)調(diào)用該方法的實(shí)例,來決定調(diào)用哪個(gè)方法。對(duì)子類的一個(gè)實(shí)例,如果子類重寫了父類的方法,則運(yùn)行時(shí)系統(tǒng)調(diào)用子類的方法;如果子類繼承了父類的方法(未重寫),則運(yùn)行時(shí)系統(tǒng)調(diào)用父類的方法。
方法重寫時(shí)應(yīng)遵循的原則:
1)改寫后的方法不能比被重寫的方法有更嚴(yán)格的訪問權(quán)限(可以相同)。
2)改寫后的方法不能比重寫的方法產(chǎn)生更多的例外。
注:重載用于同一個(gè)類中的同名方法,重寫用于具有繼承關(guān)系的父子類的同名方法。
常用關(guān)鍵字釋疑
1)static
static變量:所有此類實(shí)例共享此靜態(tài)變量,也就是說在類裝載時(shí),只分配一塊存儲(chǔ)空間,所有此類的對(duì)象都可以操控此塊存儲(chǔ)空間。
static方法:無需本類的對(duì)象即可調(diào)用此方法,調(diào)用一個(gè)靜態(tài)方法就是“類名.方法名”。
static類:通常一個(gè)普通類不允許聲明為靜態(tài)的,只有一個(gè)內(nèi)部類才可以。這時(shí)這個(gè)聲明為靜態(tài)的內(nèi)部類可以直接作為一個(gè)普通類來使用,而不需實(shí)例一個(gè)外部類。
2)final
final成員:對(duì)基本類型來說是其值不可變,而對(duì)于對(duì)象變量來說其引用不可再變。初始化可以在兩個(gè)地方,一是其定義處,也就是說在final變量定義時(shí)直接給其賦值,二是在構(gòu)造函數(shù)中。這兩個(gè)地方只能選其一,要么在定義時(shí)給值,要么在構(gòu)造函數(shù)中給值,不能同時(shí)既在定義時(shí)給了值,又在構(gòu)造函數(shù)中給另外的值。
final方法:將方法聲明為final,那就說明你已經(jīng)知道這個(gè)方法提供的功能已經(jīng)滿足你要求,不需要進(jìn)行擴(kuò)展,并且也不允許任何從此類繼承的類來覆寫這個(gè)方法,但是繼承仍然可以繼承這個(gè)方法,也就是說可以直接使用。
final類:final類與普通類的使用幾乎沒有差別,只是它失去了被繼承的特性。
3)super、this(常用于構(gòu)造方法中)
super的用法:
訪問父類被隱藏的成員變量,如:
super.variable;
調(diào)用父類中被重寫的方法,如:
super.Method([paramlist]);
調(diào)用父類的構(gòu)造函數(shù),如:
super([paramlist]);
this通常指代當(dāng)前對(duì)象,super通常指代父類。在構(gòu)造方法中super后加參數(shù)的是用來調(diào)用父類中具有相同形式的構(gòu)造函數(shù);this后加參數(shù)則調(diào)用的是當(dāng)前具有相同參數(shù)的構(gòu)造函數(shù)
對(duì)象的操作控制
對(duì)象的生成:
聲明:聲明并不為對(duì)象分配內(nèi)存空間,而只是分配一個(gè)引用空間;對(duì)象的引用類似于指針,是32位的地址空間,它的值指向一個(gè)中間的數(shù)據(jù)結(jié)構(gòu),它存儲(chǔ)有關(guān)數(shù)據(jù)類型的信息以及當(dāng)前對(duì)象所在的堆的地址,而對(duì)于對(duì)象所在的實(shí)際的內(nèi)存地址是不可操作的,這就保證了安全性。實(shí)例化:運(yùn)算符new為對(duì)象分配內(nèi)存空間,它調(diào)用對(duì)象的構(gòu)造方法,返回引用;一個(gè)類的不同對(duì)象分別占據(jù)不同的內(nèi)存空間。
對(duì)象的使用:
由于封裝性的基本原則是指對(duì)外提供接口而盡量不提供public的成員變量,所以一般也只能使用“.”來引用類中的成員方法。對(duì)象的使用實(shí)際是傳遞消息以改變某些屬性或進(jìn)行某些操作。
對(duì)象的清除:
Java的垃圾收集器自動(dòng)掃描對(duì)象的動(dòng)態(tài)內(nèi)存區(qū),把沒有引用的對(duì)象作為垃圾收集起來并釋放。System.gc( ); 當(dāng)系統(tǒng)內(nèi)存用盡或調(diào)用System.gc( )要求垃圾回收時(shí),垃圾回收線程與系統(tǒng)同步運(yùn)行。
繼承(抽象類)、接口
抽象類:
abstract class abstractClass{ …} //抽象類
abstract returnType abstractMethod([paramlist]) //抽象方法
抽象類必須被繼承,抽象方法必須被重寫。抽象方法只需聲明,無需實(shí)現(xiàn);抽象類不能被實(shí)例化,抽象類不一定要包含抽象方法。若類中包含了抽象方法,則該類必須被定義為抽象類。
接口:
[public] interface interfaceName[extends listOfSuperInterface] { … }
接口是抽象類的一種,只包含常量和方法的定義,而沒有變量和方法的實(shí)現(xiàn),且其方法都是抽象方法。
注:
一個(gè)類只能使用一次繼承關(guān)系,但卻可以有多個(gè)接口。
抽象類表示的是"is a"關(guān)系,接口表示的是"like a"關(guān)系。(涉及到設(shè)計(jì)模式)
內(nèi)部類
內(nèi)部類是在一個(gè)類的內(nèi)部嵌套定義的類,它可以是其它類的成員,也可以在一個(gè)語句塊的內(nèi)部定義,還可以在表達(dá)式內(nèi)部匿名定義。
匿名類是一種特殊的內(nèi)部類,它是在一個(gè)表達(dá)式內(nèi)部包含一個(gè)完整的類定義(消息響應(yīng)類等)。
內(nèi)部類優(yōu)缺點(diǎn)比較:
◇ 優(yōu)點(diǎn):節(jié)省編譯后產(chǎn)生的字節(jié)碼文件的大小
◇ 缺點(diǎn):使程序結(jié)構(gòu)不清楚
--------------------------------------------------------------------------------
常用數(shù)據(jù)結(jié)構(gòu)
Vector
ArrayList
List
Queue
Map
Tree
Stack
Hashtable
Enumeration
等等。。。
注:一般這些數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)存取都是以O(shè)ject為對(duì)象的,因此從其中取出的數(shù)據(jù)要進(jìn)行類型轉(zhuǎn)換,另int等不能直接存入這些數(shù)據(jù)結(jié)構(gòu)中,必須使用外覆類(如Integer等)進(jìn)行重新包裝才能存入。
Java比C++更易于使用的一方面應(yīng)該就是Java提供了豐富的數(shù)據(jù)結(jié)構(gòu)給用戶而不必讓用戶自己設(shè)計(jì)半天數(shù)據(jù)結(jié)構(gòu),最后搞了半天卻發(fā)現(xiàn)還是錯(cuò)誤百出,郁悶不已。由于Sun將這些數(shù)據(jù)結(jié)構(gòu)封裝得很好,所以只要理解這些數(shù)據(jù)結(jié)構(gòu)的特點(diǎn)和了解他們的接口方法就可以使用他們了。
一般在學(xué)習(xí)開發(fā)中可以在需要時(shí)查幫助文檔就可以搞定了,不過只有深刻地理解這些數(shù)據(jù)結(jié)構(gòu)的特性才能選擇最佳的數(shù)據(jù)結(jié)構(gòu)開發(fā)出優(yōu)秀的代碼。
--------------------------------------------------------------------------------
異常處理機(jī)制
異常實(shí)際上是程序中錯(cuò)誤導(dǎo)致中斷了正常的指令流的一種事件。
所有的例外類都直接或間接地繼承于Throwable類。Throwable又分為兩大子類Error和Exception,其中Error由虛擬機(jī)直接處理,部分Exception由用戶處理。
捕獲例外的一般框架:
try{
......
}catch( ExceptionName1 e ){
......
System.out.println( "message: " + e.getMessage() ); //e.getMessage( )是類Throwable所提供的方法,用來得到有關(guān)異常事件的信息。
}catch( ExceptionName2 e ){
......
e.printStackTrace( System.out ); //e.printStackTrace( )用來跟蹤異常事件發(fā)生時(shí)執(zhí)行堆棧的內(nèi)容。
}
......
}finally{
...... //此部分無論是否產(chǎn)生例外均需執(zhí)行,除非System.exit(0)
}
當(dāng)Java運(yùn)行時(shí)系統(tǒng)得到一個(gè)例外對(duì)象時(shí),它將會(huì)沿著方法的調(diào)用棧逐層回溯,尋找處理這一例外的代碼。找到能夠處理這種類型的例外的方法后,運(yùn)行時(shí)系統(tǒng)把當(dāng)前例外對(duì)象交給這個(gè)方法進(jìn)行處理,這一過程稱為捕獲(catch)例外。
注:捕獲例外的順序和catch語句的順序有關(guān),當(dāng)捕獲到一個(gè)例外時(shí),剩下的catch語句就不再進(jìn)行匹配。因此,在安排catch語句的順序時(shí),首先應(yīng)該捕獲最特殊的例外,然后再逐漸一般化。也就是一般先安排子類,再安排父類。
throws與throw
throw是語句拋出一個(gè)異常,throws是方法拋出一個(gè)異常。
throw:throw<異常對(duì)象>
throws:[<修飾符>]<返回值><方法名>([<參數(shù)列表>])[throws<異常類>]
聲明拋棄例外
如果在一個(gè)方法中生成了一個(gè)例外,但是這一方法并不確切地知道該如何對(duì)這一異常事件進(jìn)行處理,這時(shí),一個(gè)方法就應(yīng)該聲明拋棄例外,使得例外對(duì)象可以從調(diào)用棧向后傳播,直到有合適的方法捕獲它為止。聲明拋棄例外是在一個(gè)方法聲明中的throws子句中指明的。例如:
public int read () throws IOException {
......
}
拋出例外
拋出例外就是產(chǎn)生例外對(duì)象的過程,首先要生成例外對(duì)象,例外或者由虛擬機(jī)生成,或者由某些類的實(shí)例生成,也可以在程序中生成。在方法中,拋出例外對(duì)象是通過throw語句實(shí)現(xiàn)的。
例如:
IOException e = new IOException();
throw e ; //人為拋出異常
注:throw是明確拋出一個(gè)異常給上層;throws是標(biāo)明一個(gè)方法可能拋出的各種異常。
throws可以單獨(dú)使用,throw不能。
自定義異常
異常是一個(gè)類,用戶定義的異常必須繼承自Throwable或Exception類,建議用Exception類。
常見的異常
ArithmeticException
ArrayIndexOutOfBandsException
ArrayStoreException
IOException
FileNotFoundException
NullPointerException
MalformedURLException
NumberFormatException
OutOfMemoryException
--------------------------------------------------------------------------------
圖像處理和音頻操作
圖像處理
Java在桌面程序的功能不是非常的強(qiáng)大,因此較少用于開發(fā)桌面程序,但這方面的知識(shí)還是需要了解一下。一般圖像處理分為應(yīng)用程序中和Applet中:
應(yīng)用程序中的圖像一般都封裝成ImageIcon,在將其貼到Button、Label上,如:
JButton btn = new JButton();
ImageIcon img = new ImageIcon(path);
btn.setIcon(img);
Applet中一般直接從文件從取出圖像直接使用,如:
Image img = new Image();
Img = getImage(getDocumentBase(),imageFile);
……..
2D繪圖一般都在Applet中實(shí)現(xiàn),通過復(fù)寫paint方法實(shí)現(xiàn)。在應(yīng)用程序中也可自己new一個(gè)Graphics得到繪圖句柄。具體的平移、翻轉(zhuǎn)等算法不再此述。
注:awt中一般用paint,swing中則用paintComponent
雙緩沖,有時(shí)圖像在刷新時(shí)會(huì)產(chǎn)生閃爍,可以用雙緩沖進(jìn)行改善。雙緩沖是在圖像進(jìn)行update時(shí)再創(chuàng)建一個(gè)繪圖句柄進(jìn)行繪圖。
音頻操作
音頻操作和圖像處理也是類似的,一般也用于Applet中實(shí)現(xiàn),如:
AudioClip first = getAudioClip(getDocumentBase(),"first.au");
first.play();
如果要在應(yīng)用程序中實(shí)現(xiàn)音頻操作,可以通過Applet轉(zhuǎn)換,如:
Audio audio = Applet.newAudioClip(audio_path);
audio.play();
注:Java實(shí)現(xiàn)的音頻操作是很弱的,一般只用于播放midi、au等格式的音頻文件,而對(duì)于mp3等若要播放必須有解碼器,但實(shí)現(xiàn)起來是很不劃算的(比較復(fù)雜)。
--------------------------------------------------------------------------------
圖形化界面(swing)
Swing簡介
Swing是由100%純Java實(shí)現(xiàn)的,Swing組件是用Java實(shí)現(xiàn)的輕量級(jí)( light-weight)組件,沒有本地代碼,不依賴操作系統(tǒng)的支持,這是它與AWT組件的最大區(qū)別。
Swing采用了一種MVC的設(shè)計(jì)范式,即"模型-視圖-控制"(Model-View-Controller),其中模型用來保存內(nèi)容,視圖用來顯示內(nèi)容,控制器用來控制用戶輸入。
Swing的類層次結(jié)構(gòu)
在javax.swing包中,定義了兩種類型的組件:頂層容器(JFrame,JApplet,JDialog和JWindow)和輕量級(jí)組件。Swing組件都是AWT的Container類的直接子類和間接子類。
java.awt.Component
-java.awt.Container
-java.awt.Window
-java.awt.Frame-javax.swing.JFrame
-javax.Dialog-javax.swing.JDialog
-javax.swing.JWindow
-java.awt.Applet-javax.swing.JApplet
-javax.swing.Box
-javax.swing.Jcomponet
MVC(Model-View-Control)體系結(jié)構(gòu)
在一個(gè)MVC用戶界面中,存三個(gè)通訊對(duì)象:模型、視圖和控件。模型是指定的邏輯表示法,視圖是模型的可視化表示法,而控件則指定了如何處理用戶輸入。當(dāng)模型發(fā)生改變時(shí),它會(huì)通知所有依賴它的視圖,視圖使用控件指定其相應(yīng)機(jī)制。MVC是現(xiàn)有的編程語言中制作圖形用戶界面的一種通用的思想,其思路是把數(shù)據(jù)的內(nèi)容本身和顯示方式分離開,這樣就使得數(shù)據(jù)的顯示更加靈活多樣。
在Swing組件中,使用JComponent類的registerKeyboardAction()方法,能使用戶通過鍵盤操作來替代鼠標(biāo)驅(qū)動(dòng)GUI上Swing組件的相應(yīng)動(dòng)作。
Swing程序結(jié)構(gòu)簡介
Swing的程序設(shè)計(jì)一般可按照下列流程進(jìn)行:
1. 引入Swing包
2. 選擇"外觀和感覺"
3. 設(shè)置頂層容器
4. 設(shè)置按鈕和標(biāo)簽
5. 向容器中添加組件
6. 在組件周圍添加邊界
7. 進(jìn)行事件處理
組件的分類:
組件從功能上分可分為:
①頂層容器:JFrame,JApplet,JDialog,JWindow共4個(gè)
②中間容器:JPanel,JScrollPane,JSplitPane,JToolBar
③特殊容器:在GUI上起特殊作用的中間層,如JInternalFrame,JLayeredPane,JRootPane.④基本控件:實(shí)現(xiàn)人際交互的組件,如Jbutton, JComboBox, JList, JMenu, JSlider, JtextField。
⑤不可編輯信息的顯示:向用戶顯示不可編輯信息的組件,例如JLabel, JProgressBar, ToolTip。
⑥可編輯信息的顯示:向用戶顯示能被編輯的格式化信息的組件,如JColorChooser, JFileChoose, JFileChooser,Jtable, JtextArea。
JComponent類的特殊功能又分為:
1) 邊框設(shè)置:使用setBorder()方法可以設(shè)置組件外圍的邊框,使用一個(gè)EmptyBorder對(duì)象能在組件周圍留出空白。
2) 雙緩沖區(qū):使用雙緩沖技術(shù)能改進(jìn)頻繁變化的組件的顯示效果。與AWT組件不同,JComponent組件默認(rèn)雙緩沖區(qū),不必自己重寫代碼。如果想關(guān)閉雙緩沖區(qū),可以在組件上施加setDoubleBuffered(false)方法。
3) 提示信息:使用setTooltipText()方法,為組件設(shè)置對(duì)用戶有幫助的提示信息。
4) 鍵盤導(dǎo)航:使用registerKeyboardAction( ) 方法,能使用戶用鍵盤代替鼠標(biāo)來驅(qū)動(dòng)組件。JComponent類的子類AbstractButton還提供了便利的方法--用setMnemonic( )方法指明一個(gè)字符,通過這個(gè)字符和一個(gè)當(dāng)前L&F的特殊修飾共同激活按鈕動(dòng)作。
5) 可插入L&F:每個(gè)Jcomponent對(duì)象有一個(gè)相應(yīng)的ComponentUI對(duì)象,為它完成所有的繪畫、事件處理、決定尺寸大小等工作。 ComponentUI對(duì)象依賴當(dāng)前使用的L&F,用UIManager.setLookAndFeel( )方法可以設(shè)置需要的L&F.
6) 支持布局:通過設(shè)置組件最大、最小、推薦尺寸的方法和設(shè)置X、Y對(duì)齊參數(shù)值的方法能指定布局管理器的約束條件,為布局提供支持。
使用Swing的基本規(guī)則
與AWT組件不同,Swing組件不能直接添加到頂層容器中,它必須添加到一個(gè)與Swing頂層容器相關(guān)聯(lián)的內(nèi)容面板(content pane)上。內(nèi)容面板是頂層容器包含的一個(gè)普通容器,它是一個(gè)輕量級(jí)組件。基本規(guī)則如下:
(1)把Swing組件放入一個(gè)頂層Swing容器的內(nèi)容面板上
(2)避免使用非Swing的重量級(jí)組件。
對(duì)JFrame添加組件有兩種方式:
1) 用getContentPane( )方法獲得JFrame的內(nèi)容面板,再對(duì)其加入組件:frame.getContentPane().add(childComponent)
2) 建立一個(gè)Jpanel或 JDesktopPane之類的中間容器,把組件添加到容器中,用setContentPane()方法把該容器置為JFrame的內(nèi)容面板:
Jpanel contentPane=new Jpanel( );
...... //把其它組件添加到Jpanel中;
frame.setContentPane(contentPane);
//把contentPane對(duì)象設(shè)置成為frame的內(nèi)容面板
各種容器面板和組件
根面板
根面板由一個(gè)玻璃面板(glassPane)、一個(gè)內(nèi)容面板(contentPane)和一個(gè)可選擇的菜單條(JMenuBar)組成,而內(nèi)容面板和可選擇的菜單條放在同一分層。玻璃面板是完全透明的,缺省值為不可見,為接收鼠標(biāo)事件和在所有組件上繪圖提供方便。
根面板提供的方法:
Container getContentPane(); //獲得內(nèi)容面板
setContentPane(Container); //設(shè)置內(nèi)容面
JMenuBar getMenuBar( ); //活動(dòng)菜單條
setMenuBar(JMenuBar); //設(shè)置菜單條
JLayeredPane getLayeredPane(); //獲得分層面板
setLayeredPane(JLayeredPane); //設(shè)置分層面板
Component getGlassPane(); //獲得玻璃面板
setGlassPane(Component); //設(shè)置玻璃面板
分層面板
Swing提供兩種分層面板:JlayeredPane和JDesktopPane。 JDesktopPane是JLayeredPane的子類,專門為容納內(nèi)部框架(JInternalFrame)而設(shè)置。向一個(gè)分層面板中添加組件,需要說明將其加入哪一層,指明組件在該層中的位置:
add(Component c, Integer Layer, int position)。
滾動(dòng)窗口(JScrollPane)
分隔板(JSplitPane)
選項(xiàng)板(JTabbedPane)
工具欄(JToolBar)
內(nèi)部框架(JInternalFrame)
內(nèi)部框架JInternalFrame就如同一個(gè)窗口在另一個(gè)窗口內(nèi)部,其特點(diǎn)如下:
1) 必須把內(nèi)部框架添加到一個(gè)容器中(通常為JDesktopPane),否則不顯示;
2) 不必調(diào)用show()或setVisible()方法,內(nèi)部框架隨所在的容器一起顯示;
3) 必須用setSize()或pack()或setBounds方法設(shè)置框架尺寸,否則尺寸為零,框架不能顯示;
4) 可以用setLocation()或setBounds( ) 方法設(shè)置內(nèi)部框架在容器中的位置,缺省值為0,0,即容器的左上角;
5) 象頂層JFrame一樣,對(duì)內(nèi)部框架添加組件也要加在它的內(nèi)容面板上;
6) 在內(nèi)部框架中建立對(duì)話框,不能使用JDialog作為頂層窗口,必須用JOptionPane或JInternalFrame;
7) 內(nèi)部框架不能監(jiān)聽窗口事件,可以通過監(jiān)聽與窗口事件類似的內(nèi)部框架(JInternalFrameEvent)處理內(nèi)部框架窗口的操作。
按鈕(JButton)
復(fù)選框(JCheckBox)
單選框(JRadioButton)
選擇框(JComboBox)
文件選擇器(JFileChooser)
標(biāo)簽(JLabel)
列表(List)
菜單(JMenu)
進(jìn)程條(JProgressBar)
滑動(dòng)條(JSlider)
表格(JTable)
樹(JTree)
布局管理器
Swing雖然有頂層容器,但是我們不能把組件直接加到頂層容器中,Swing窗體中含有一個(gè)稱為內(nèi)容面板的容器(ContentPane),在頂層容器上放內(nèi)容面板,然后把組件加入到內(nèi)容面板中BoxLayout布局管理器按照自上而下(y軸)或者從左到右(x軸)的順序布局依次加入組件。建立一個(gè)BoxLayout對(duì)象,必須指明兩個(gè)參數(shù):被布局的容器和BoxLayout的主軸。缺省情況下,組件在縱軸方向上居中對(duì)齊。
設(shè)置布局管理器的方法如下:
pane.setLayout(new BoxLayout(pane,BoxLayout.Y-AXIS));
圖形化界面需要了解但不必花太大精力,因?yàn)檫@方面知識(shí)更新太快,而且也不是主流技術(shù)。最近又興SWT了,不知會(huì)否代替Swing成為開發(fā)人員的新歡。而且隨著開發(fā)工具的發(fā)展,圖形化界面將變得非常簡單易用(不只會(huì)不會(huì)做得和Delphi一樣),JBuider就做得不錯(cuò),所以最好還是將精力花在其它技術(shù)上,對(duì)于圖形界面的美化在需要的時(shí)候再即學(xué)即用為好,個(gè)人觀點(diǎn)。
--------------------------------------------------------------------------------
多線程技術(shù)
㈠線程的實(shí)現(xiàn)
Thread類
定義一個(gè)線程類,它繼承線程類Thread并重寫其中的方法 run(),這時(shí)在初始化這個(gè)類的實(shí)例時(shí),目標(biāo)target可為null,表示由這個(gè)實(shí)例來執(zhí)行線程體。由于Java只支持單重繼承,用這種方法定義的類不能再繼承其它父類。
直接繼承Thread類:
1) 不能再從其他類繼承;
2) 編寫簡單,可以直接操縱線程,無需使用Thread.currentThread()。
Runnable接口:
提供一個(gè)實(shí)現(xiàn)接口Runnable的類作為一個(gè)線程的目標(biāo)對(duì)象,在初始化一個(gè)Thread類或者Thread子類的線程對(duì)象時(shí),把目標(biāo)對(duì)象傳遞給這個(gè)線程實(shí)例,由該目標(biāo)對(duì)象提供線程體 run()。這時(shí),實(shí)現(xiàn)接口Runnable的類仍然可以繼承其它父類。
使用Runnable接口:
1) 可以將CPU、代碼和數(shù)據(jù)分開,形成清晰的模型;
2) 還可以從其他類繼承;
3) 保持程序風(fēng)格的一致性。
例:
Thread t1 = new MyThread("T1"); //extends
clockThread = new Thread(this, "Clock"); //Runnable
㈡線程的調(diào)度
線程調(diào)度器按線程的優(yōu)先級(jí)高低選擇高優(yōu)先級(jí)線程(進(jìn)入運(yùn)行中狀態(tài))執(zhí)行。線程的優(yōu)先級(jí)用數(shù)字來表示范圍從1到10,即Thread.MIN_PRIORITY到Thread.MAX_PRIORITY。一個(gè)線程的缺省優(yōu)先級(jí)是5,即Thread.NORM_PRIORITY。
例:void setPriority(int newPriority);
線程的控制
終止線程
stop()來終止線程
測試線程狀態(tài)
通過Thread 中的isAlive() 方法來獲取線程是否處于活動(dòng)狀態(tài)
線程的暫停和恢復(fù)
1) sleep() 方法
2) join()
線程的互斥與同步
為解決操作的不完整性問題,在Java 語言中,引入了對(duì)象互斥鎖的概念,來保證共享數(shù)據(jù)操作的完整性。每個(gè)對(duì)象都對(duì)應(yīng)于一個(gè)可稱為" 互斥鎖" 的標(biāo)記,這個(gè)標(biāo)記用來保證在任一時(shí)刻,只能有一個(gè)線程訪問該對(duì)象。關(guān)鍵字synchronized 來與對(duì)象的互斥鎖聯(lián)系。
例:
public void push(char c) {
synchronized(this) { //this表示Stack的當(dāng)前對(duì)象
data[idx] = c;
idx++;
}
}
public char pop() {
synchronized(this) {
idx--;
return data[idx];
}
}
synchronized還可修飾方法和類
注意:
wait、nofity、notifyAll必須在已經(jīng)持有鎖的情況下執(zhí)行,所以它們只能出現(xiàn)在synchronized作用的范圍內(nèi),也就是出現(xiàn)在用synchronized修飾的方法或類中。
線程組
線程是被個(gè)別創(chuàng)建的,但可以將它們歸類到線程組中,以便于調(diào)試和監(jiān)視。只能在創(chuàng)建線程的同時(shí)將它與一個(gè)線程組相關(guān)聯(lián)。在使用大量線程的程序中,使用線程組組織線程可能很有幫助。
線程間通信
當(dāng)線程在繼續(xù)執(zhí)行前需要等待一個(gè)條件時(shí),僅有 synchronized 關(guān)鍵字是不夠的。雖然 synchronized 關(guān)鍵字阻止并發(fā)更新一個(gè)對(duì)象,但它沒有實(shí)現(xiàn)線程間發(fā)信。Object 類為此提供了三個(gè)函數(shù):wait()、notify() 和 notifyAll()。
--------------------------------------------------------------------------------
I/O操作
兩大基類:InputStream和OutputStream、Reader和Writer
Ⅰ字節(jié)流:
從InputStream和OutputStream派生出來的一系列類。這類流以字節(jié)(byte)為基本處理單位。
◇ InputStream、OutputStream
◇ FileInputStream、FileOutputStream
◇ PipedInputStream、PipedOutputStream
◇ ByteArrayInputStream、ByteArrayOutputStream
◇ FilterInputStream、FilterOutputStream
◇ DataInputStream、DataOutputStream
◇ BufferedInputStream、BufferedOutputStream
Ⅱ字符流:
從Reader和Writer派生出的一系列類,這類流以16位的Unicode碼表示的字符為基本處理單位。
◇ Reader、Writer //抽象基類
◇ InputStreamReader、OutputStreamWriter
◇ FileReader、FileWriter
◇ CharArrayReader、CharArrayWriter
◇ PipedReader、PipedWriter
◇ FilterReader、FilterWriter
◇ BufferedReader、BufferedWriter
◇ StringReader、StringWriter
Ⅲ對(duì)象流
◇ ObjectInputStream、ObjectOutputStream
Ⅳ其它
◇ 文件處理:
File、RandomAccessFile;
◇ 接口
DataInput、DataOutput、ObjectInput、ObjectOutput;
類File提供了一種與機(jī)器無關(guān)的方式來描述一個(gè)文件對(duì)象的屬性。
類FileInputStream和FileOutputStream用來進(jìn)行文件I/O處理,由它們所提供的方法可以打開本地主機(jī)上的文件,并進(jìn)行順序的讀/寫。
隨機(jī)訪問文件則允許對(duì)文件內(nèi)容進(jìn)行隨機(jī)讀/寫。在java中,類RandomAccessFile 提供了隨機(jī)訪問文件的方法。
過濾流在讀/寫數(shù)據(jù)的同時(shí)可以對(duì)數(shù)據(jù)進(jìn)行處理,它提供了同步機(jī)制,使得某一時(shí)刻只有一個(gè)線程可以訪問一個(gè)I/O流,以防止多個(gè)線程同時(shí)對(duì)一個(gè)I/O流進(jìn)行操作所帶來的意想不到的結(jié)果。類FilterInputStream和FilterOutputStream分別作為所有過濾輸入流和輸出流的父類。
幾種常見的過濾流
◇ BufferedInputStream和BufferedOutputStream
緩沖流,用于提高輸入/輸出處理的效率。
◇ DataInputStream 和 DataOutputStream
不僅能讀/寫數(shù)據(jù)流,而且能讀/寫各種的java語言的基本類型。
◇ LineNumberInputStream
除了提供對(duì)輸入處理的支持外,LineNumberInputStream可以記錄當(dāng)前的行號(hào)。
◇ PushbackInputStream
提供了一個(gè)方法可以把剛讀過的字節(jié)退回到輸入流中,以便重新再讀一遍。
◇ PrintStream
打印流的作用是把Java語言的內(nèi)構(gòu)類型以其字符表示形式送到相應(yīng)的輸出流。
字符流的處理
java中提供了處理以16位的Unicode碼表示的字符流的類,即以Reader和Writer 為基類派生出的一系列類。
ⅠReader類是處理所有字符流輸入類的父類。
ⅡWriter類是處理所有字符流輸出類的父類。
這兩個(gè)類是抽象類,只是提供了一系列用于字符流處理的接口,不能生成這兩個(gè)類的實(shí)例,只能通過使用由它們派生出來的子類對(duì)象來處理字符流。如InputStreamReader和OutputStreamWriter;BufferedReader和BufferedWriter等.
對(duì)象串行化
對(duì)象的壽命通常隨著生成該對(duì)象的程序的終止而終止。有時(shí)候,可能需要將對(duì)象的狀態(tài)保存下來,在需要時(shí)再將對(duì)象恢復(fù)。我們把對(duì)象的這種能記錄自己的狀態(tài)以便將來再生的能力,叫做對(duì)象的持續(xù)性(persistence)。對(duì)象通過寫出描述自己狀態(tài)的數(shù)值來記錄自己,這個(gè)過程叫對(duì)象的串行化(Serialization)。實(shí)現(xiàn)串行化需繼承 Serializable接口。java.io包中,提供了ObjectInputStream和ObjectOutputStream將數(shù)據(jù)流功能擴(kuò)展至可讀寫對(duì)象。
串行化能保存的元素
只能保存對(duì)象的非靜態(tài)成員變量,不能保存任何的成員方法和靜態(tài)的成員變量,而且串行化保存的只是變量的值,對(duì)于變量的任何修飾符,都不能保存。
transient關(guān)鍵字
對(duì)于某些類型的對(duì)象,其狀態(tài)是瞬時(shí)的,這樣的對(duì)象是無法保存其狀態(tài)的,例如一個(gè)Thread對(duì)象,或一個(gè)FileInputStream對(duì)象,對(duì)于這些字段,我們必須用transient關(guān)鍵字標(biāo)明
定制串行化
缺省的串行化機(jī)制,對(duì)象串行化首先寫入類數(shù)據(jù)和類字段的信息,然后按照名稱的上升排列順序?qū)懭肫鋽?shù)值。如果想自己明確地控制這些數(shù)值的寫入順序和寫入種類,必須定義自己的讀取數(shù)據(jù)流的方式。就是在類的定義中重寫writeObject()和readObject()方法。
注意:在使用完流(或文件)后必須記得講流(或文件)關(guān)閉:in.close(); out.close(); f.close();
流類處理的幾種常見情況(流間組合):
Ⅰ BufferedInputStream bis = new BufferedInputStream(System.in);
BufferedOutputStream bos = new BufferedOutputStream(new File("filename"));
Ⅱ InputStreamReader in = new InputStreamReader(System.in);
OutputStreamWriter out = new OutputStreamWriter(new
FileOutputStream("filename.txt"));
Ⅲ BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream ("filename.txt"));
PrintWriter out = new PrintWriter(new FileWriter("filename.txt"));
Ⅳ FileInputStream fin = new FileInputStream(filename); /
FileOutputStream fos = new FileOutputStream(new File("filename"));
Ⅴ DataInputStream din = new DataInputStream(new FileInputStream("filename.dat")));
DataInputStream din = new DataInputStream(newBufferedInputStream (new
FileInputStream ("filename.dat")));
Ⅵ ObjectInputStream s = new ObjectInputStream(new FileInputStream("filename.ser"));
ObjectOutputStream s = new ObjectOutputStream(new
FileOutputStream("filename.ser"));
Ⅶ RandomAccessFile inOut = new RandomAccessFile("filename.dat", "rw");
--------------------------------------------------------------------------------
基本網(wǎng)絡(luò)技術(shù)
原理:
在TCP/IP協(xié)議中IP層主要負(fù)責(zé)網(wǎng)絡(luò)主機(jī)的定位,數(shù)據(jù)傳輸?shù)穆酚桑蒊P地址可以唯一地確定Internet上的一臺(tái)主機(jī)。而TCP層則提供面向應(yīng)用的可靠的或非可靠的數(shù)據(jù)傳輸機(jī)制,這是網(wǎng)絡(luò)編程的主要對(duì)象,一般不需要關(guān)心IP層是如何處理數(shù)據(jù)的。目前較為流行的網(wǎng)絡(luò)編程模型是客戶機(jī)/服務(wù)器(C/S)結(jié)構(gòu)。即通信雙方一方作為服務(wù)器等待客戶提出請求并予以響應(yīng)。客戶則在需要服務(wù)時(shí)向服務(wù)器提出申請。服務(wù)器一般作為守護(hù)進(jìn)程始終運(yùn)行,監(jiān)聽網(wǎng)絡(luò)端口,一旦有客戶請求,就會(huì)啟動(dòng)一個(gè)服務(wù)進(jìn)程來響應(yīng)該客戶,同時(shí)自己繼續(xù)監(jiān)聽服務(wù)端口,使后來的客戶也能及時(shí)得到服務(wù)。
網(wǎng)絡(luò)基本概念
IP地址:標(biāo)識(shí)計(jì)算機(jī)等網(wǎng)絡(luò)設(shè)備的網(wǎng)絡(luò)地址,由四個(gè)8位的二進(jìn)制數(shù)組成,中間以小數(shù)點(diǎn)分隔。
主機(jī)名(hostname):網(wǎng)絡(luò)地址的助記名,按照域名進(jìn)行分級(jí)管理。
端口號(hào)(port number):網(wǎng)絡(luò)通信時(shí)同一機(jī)器上的不同進(jìn)程的標(biāo)識(shí)。
服務(wù)類型(service):網(wǎng)絡(luò)的各種服務(wù)。
注意:通常一臺(tái)主機(jī)上總是有很多個(gè)進(jìn)程需要網(wǎng)絡(luò)資源進(jìn)行網(wǎng)絡(luò)通訊。網(wǎng)絡(luò)通訊的對(duì)象準(zhǔn)確的講不是主機(jī),而應(yīng)該是主機(jī)中運(yùn)行的進(jìn)程。這時(shí)候光有主機(jī)名或IP地址來標(biāo)識(shí)這么多個(gè)進(jìn)程顯然是不夠的。端口號(hào)就是為了在一臺(tái)主機(jī)上提供更多的網(wǎng)絡(luò)資源而采取得一種手段,也是TCP層提供的一種機(jī)制。只有通過主機(jī)名或IP地址和端口號(hào)的組合才能唯一的確定網(wǎng)絡(luò)通訊中的對(duì)象:進(jìn)程。
兩類傳輸協(xié)議:TCP;UDP
TCP是Tranfer Control Protocol的簡稱,是一種面向連接的保證可靠傳輸?shù)膮f(xié)議。通過TCP協(xié)議傳輸,得到的是一個(gè)順序的無差錯(cuò)的數(shù)據(jù)流。發(fā)送方和接收方的成對(duì)的兩個(gè)socket之間必須建立連接,以便在TCP協(xié)議的基礎(chǔ)上進(jìn)行通信,當(dāng)一個(gè)socket(通常都是server socket)等待建立連接時(shí),另一個(gè)socket可以要求進(jìn)行連接,一旦這兩個(gè)socket連接起來,它們就可以進(jìn)行雙向數(shù)據(jù)傳輸,雙方都可以進(jìn)行發(fā)送或接收操作。
UDP是User Datagram Protocol的簡稱,是一種無連接的協(xié)議,每個(gè)數(shù)據(jù)報(bào)都是一個(gè)獨(dú)立的信息,包括完整的源地址或目的地址,它在網(wǎng)絡(luò)上以任何可能的路徑傳往目的地,因此能否到達(dá)目的地,到達(dá)目的地的時(shí)間以及內(nèi)容的正確性都是不能被保證的。
注意:既然有了保證可靠傳輸?shù)腡CP協(xié)議,為什么還要非可靠傳輸?shù)腢DP協(xié)議呢?主要的原因有兩個(gè)。一是可靠的傳輸是要付出代價(jià)的,對(duì)數(shù)據(jù)內(nèi)容正確性的檢驗(yàn)必然占用計(jì)算機(jī)的處理時(shí)間和網(wǎng)絡(luò)的帶寬,因此TCP傳輸?shù)男什蝗鏤DP高。二是在許多應(yīng)用中并不需要保證嚴(yán)格的傳輸可靠性,比如視頻會(huì)議系統(tǒng),并不要求音頻視頻數(shù)據(jù)絕對(duì)的正確,只要保證連貫性就可以了,這種情況下顯然使用UDP會(huì)更合理一些。
創(chuàng)建一個(gè)URL
類URL的構(gòu)造方法都聲明拋棄非運(yùn)行時(shí)例外(MalformedURLException),因此生成URL對(duì)象時(shí),我們必須要對(duì)這一例外進(jìn)行處理,通常是用try-catch語句進(jìn)行捕獲。格式如下:
try {
URL myURL = new URL(...);
}catch(MalformedURLException e) {
....
}
從URL讀取WWW網(wǎng)絡(luò)資源
當(dāng)我們得到一個(gè)URL對(duì)象后,就可以通過它讀取指定的WWW資源。這時(shí)我們將使用URL的方法openStream(),其定義為:
InputStream openStream();
方法openSteam()與指定的URL建立連接并返回InputStream類的對(duì)象以從這一連接中讀取數(shù)據(jù)。
ex: BufferedReader in = new BufferedReader(new InputStreamReader((new URL(...)).openStream()));
通過URLConnetction連接WWW
類URLConnection提供了很多方法來設(shè)置或獲取連接參數(shù),程序設(shè)計(jì)時(shí)最常使用的是getInputStream()和getOurputStream(),其定義為:
InputSteram getInputSteram();
OutputSteram getOutputStream();
通過返回的輸入/輸出流我們可以與遠(yuǎn)程對(duì)象進(jìn)行通信。看下面的例子:
URL url =new URL ("http://www.javasoft.com/cgi-bin/backwards");
//創(chuàng)建一URL對(duì)象
URLConnectin con=url.openConnection();
//由URL對(duì)象獲取URLConnection對(duì)象
DataInputStream dis=new DataInputStream (con.getInputSteam());
//由URLConnection獲取輸入流,并構(gòu)造DataInputStream對(duì)象
PrintStream ps=new PrintSteam(con.getOutupSteam());
//由URLConnection獲取輸出流,并構(gòu)造PrintStream對(duì)象
String line=dis.readLine(); //從服務(wù)器讀入一行
ps.println("client…"); //向服務(wù)器寫出字符串 "client…"
基于Socket(套接字)的低層次Java網(wǎng)絡(luò)編程
網(wǎng)絡(luò)上的兩個(gè)程序通過一個(gè)雙向的通訊連接實(shí)現(xiàn)數(shù)據(jù)的交換,這個(gè)雙向鏈路的一端稱為一個(gè)Socket。Socket通常用來實(shí)現(xiàn)客戶方和服務(wù)方的連接。Socket是TCP/IP協(xié)議的一個(gè)十分流行的編程界面,一個(gè)Socket由一個(gè)IP地址和一個(gè)端口號(hào)唯一確定。
Socket通訊的一般過程:
使用Socket進(jìn)行Client/Server程序設(shè)計(jì)的一般連接過程是這樣的:Server端Listen(監(jiān)聽)某個(gè)端口是否有連接請求,Client端向Server端發(fā)出Connect(連接)請求,Server端向Client端發(fā)回Accept(接受)消息。一個(gè)連接就建立起來了。Server端和Client端都可以通過Send,Write等方法與對(duì)方通信。
對(duì)于一個(gè)功能齊全的Socket,都要包含以下基本結(jié)構(gòu),其工作過程包含以下四個(gè)基本的步驟:
(1)創(chuàng)建Socket;
(2)打開連接到Socket的輸入/出流;
(3)按照一定的協(xié)議對(duì)Socket進(jìn)行讀/寫操作;
(4)關(guān)閉Socket.
注意,在選擇端口時(shí),必須小心。每一個(gè)端口提供一種特定的服務(wù),只有給出正確的端口,才能獲得相應(yīng)的服務(wù)。0~1023的端口號(hào)為系統(tǒng)所保留
客戶端的Socket
try {
Socket socket = new Socket("127.0.0.1",8080);
}catch(IOException e) {
System.out.println("Error: " + e);
}
服務(wù)器端的ServerSocket
ServerSocket server = null;
try {
server = new ServerSocket(8080);
}catch(IOException e) {
System.out.println("can not listener to : " + e);
}
Socket socket = null;
try {
//accept()是一個(gè)阻塞方法,一旦有客戶請求,它就會(huì)返回一個(gè)Socket對(duì)象用于同客戶進(jìn)行交互
socket = server.accept();
}catch(IOException e) {
System.out.println("Error : " + e);
}
打開輸入/出流類Socket提供了方法getInputStream ()和getOutStream()來得到對(duì)應(yīng)的輸入/輸出流以進(jìn)行讀/寫 操作,這兩個(gè)方法分別返回InputStream和OutputSteam類對(duì)象。為了便于讀/寫數(shù)據(jù),我們可以在返回的輸入/輸出流對(duì)象上建立過濾流,如DataInputStream、DataOutputStream或PrintStream類對(duì)象,對(duì)于文本方式流對(duì)象,可以采用InputStreamReader和OutputStreamWriter、PrintWirter等處理。
關(guān)閉Socket
每一個(gè)Socket存在時(shí),都將占用一定的資源,在Socket對(duì)象使用完畢時(shí),要其關(guān)閉。關(guān)閉Socket可以調(diào)用Socket的Close()方法。在關(guān)閉Socket之前,應(yīng)將與Socket相關(guān)的所有的輸入/輸出流全部關(guān)閉,以釋放所有的資源。而且要注意關(guān)閉的順序,與Socket相關(guān)的所有的輸入/輸出該首先關(guān)閉,然后再關(guān)閉Socket。
數(shù)據(jù)報(bào)(Datagram)
所謂數(shù)據(jù)報(bào)(Datagram)就跟日常生活中的郵件系統(tǒng)一樣,是不能保證可靠的寄到的,而面向鏈接的TCP就好比電話,雙方能肯定對(duì)方接受到了信息。
Datagram通訊的表示方法:DatagramSocket;DatagramPacket
原理:
包java.net中提供了兩個(gè)類DatagramSocket和DatagramPacket用來支持?jǐn)?shù)據(jù)報(bào)通信,DatagramSocket用于在程序之間建立傳送數(shù)據(jù)報(bào)的通信連接, DatagramPacket則用來表示一個(gè)數(shù)據(jù)報(bào)。用數(shù)據(jù)報(bào)方式編寫client/server程序時(shí),無論在客戶方還是服務(wù)方,首先都要建立一個(gè)DatagramSocket對(duì)象,用來接收或發(fā)送數(shù)據(jù)報(bào),然后使用DatagramPacket類對(duì)象作為傳輸數(shù)據(jù)的載體。在接收數(shù)據(jù)前,應(yīng)該采用上面的第一種方法生成一個(gè)DatagramPacket對(duì)象,給出接收數(shù)據(jù)的緩沖區(qū)及其長度。然后調(diào)用DatagramSocket 的方法receive()等待數(shù)據(jù)報(bào)的到來,receive()將一直等待,直到收到一個(gè)數(shù)據(jù)報(bào)為止。
DatagramPacket packet=new DatagramPacket(buf, 256);
Socket.receive (packet);
發(fā)送數(shù)據(jù)前,也要先生成一個(gè)新的DatagramPacket對(duì)象,這時(shí)要使用上面的第二種構(gòu)造方法,在給出存放發(fā)送數(shù)據(jù)的緩沖區(qū)的同時(shí),還要給出完整的目的地址,包括IP地址和端口號(hào)。發(fā)送數(shù)據(jù)是通過DatagramSocket的方法send()實(shí)現(xiàn)的,send()根據(jù)數(shù)據(jù)報(bào)的目的地址來尋徑,以傳遞數(shù)據(jù)報(bào)。
DatagramPacket packet=new DatagramPacket(buf, length, address, port);
Socket.send(packet);
上述就是小編為大家分享的如何實(shí)現(xiàn)J2SE入門了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站名稱:如何實(shí)現(xiàn)J2SE入門
文章源于:http://www.chinadenli.net/article48/piihep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、移動(dòng)網(wǎng)站建設(shè)、全網(wǎng)營銷推廣、自適應(yīng)網(wǎng)站、網(wǎng)站營銷、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)