2.1 Java程序設計基礎
J a v a是J S P的基礎,要學習J S P技術,J a v a基礎是必不可少的。本節將簡要介紹J a v a的基本語
法和概念。已經是J a v a編程人員的讀者就不用閱讀了,這里是為沒有多少J a v a經驗的讀者提供一
個快速入門的方法。這里對J a v a語言的介紹僅僅是一個基本的概況,要想深入學習J S P,必須對
J a v a語言有深刻的理解,筆者推薦機械工業出版社翻譯出版的《J a v a編程思想》一書,本書限于
篇幅,就不多講了。
2.1.1 Java語言規則
J a v a語言的基本結構像C / C + +, 任何用面向過程語言編寫過程序的人都可以了解J a v a語言的
大部分結構。
1. 程序結構
J a v a語言的源程序代碼由一個或多個編譯單元( c o m p i l a t i o n u n i t )組成,每個編譯單元只能包
含下列內容(空格和注釋除外):
• 程序包語句(package statement )。
• 入口語句(import statements) 。
• 類的聲明(class declarations) 。
• 界面聲明(interface declarations)。
每個J a v a的編譯單元可包含多個類或界面,但是每個編譯單元最多只能有一個類或者界面是
公共的。Java 的源程序代碼被編譯后,便產生了J a v a字節代碼。J a v a的字節代碼由一系列不依
賴于機器的指令組成,這些指令能被J a v a的運行系統(runtime system)有效地解釋。J a v a的運行系
統工作起來如同一臺虛擬機。在當前的J a v a實現中,每個編譯單元就是一個以. j a v a為后綴的文件。
每個編譯單元有若干個類,編譯后,每個類生成一個. c l a s s文件。. c l a s s文件是J a v a虛擬機能夠識
別的代碼。在引入了J A R這個概念以后,現在可以把許多J a v a的c l a s s文件壓縮進入一個J A R文件
中。新版本的J a v a已經可以直接讀取J A R文件加以執行。
2. 注釋
注釋有三種類型:
/ / 注釋一行
/ * 一行或多行注釋*/
/ * * 文檔注釋**/
文檔注釋一般放在一個變量或函數定義之前,表示在任何自動生成文檔系統中調入,提取
注釋生成文檔的工具叫做j a v a d o c,其中還包括一些以@開頭的變量,如: @ s e e、@ v e r s i o n、
@ p a r a m等等,具體用法參見J D K自帶的工具文檔。
3. 標識符
變量、函數、類和對象的名稱都是標識符,程序員需要標識和使用的東西都需要標識符。
在J a v a語言里,標識符以字符_或$開頭,后面可以包含數字,標識符是大小寫有區別的,沒有長
度限制。
有效的標識符如: gogogo brood_war Hello _and_you $bill。
聲明如:
int a_number;
char _onechar;
float $bill。
以下為J a v a的關鍵字:
a b s t r a c t c o n t i n u e f o r new switch
b o o l e a n d e f a u l t g o t o n u l l synchronized
b r e a k d o i f p a c k a g e this
b y t e d o u b l e i m p l e m e n t s p r i v a t e threadsafe
b y v a l u e e l s e i m p o r t p r o t e c t e d throw
c a s e e x t e n d s i n s t a n c e o f p u b l i c transient
c a t c h f a l s e i n t r e t u r n true
char f i n a l i n t e r f a c e short try
c l a s s f i n a l l y l o n g s t a t i c void
c o n s t f l o a t n a t i v e s u p e r while
以下單詞被保留使用: c a s t、f u t u r e、g e n e r i c、i n n e r、o p e r a t o r、o u t e r、r e s t、v a r。
4. 數據類型
J a v a使用五種基本類型: i n t e g e r (整數),f l o a t i n g (浮點數),p o i n t (指針),B o o l e a n (布爾變量),
Character or String(字符或字符串)。此外,還有一些復合的數據類型,如數組等。
Integer 包含下面幾種類型:
整數長度( B i t s ) 數據類型表示
8 b y t e
1 6 short
3 2 int
6 4 l o n g
floating 下邊給出的數據表示都是浮點數的例子:
3 . 1 4 1 5 9,3 . 1 2 3 E 1 5,4 e 5
浮點數長度(Bits) 數據類型表示
3 2 f l o a t
6 4 double
Boolean 下邊是布爾變量的兩種可能取值:
t r u e false
Character 下邊給出的都是字符的例子:
第二章預備知識17
a s d f
String 下邊給出的都是字符串的例子:
"gogogo,rock and roll" " J S P高級編程"
數組可以定義任意類型的數組,如char s[],這是字符型數組; int array [],這是整型數組;
還可以定義數組的數組. intblock[][]=new int [2][3];數組邊界在運行時被檢測,以避免堆棧溢出。
在J a v a里,數組實際上是一個對象,數組有一個成員變量: l e n g t h。可以用這個成員函數來
查看任意數組的長度。
在J a v a里創建數組,可使用兩種基本方法:
1) 創建一個空數組。
int list[]=new int[50];
2) 用初始數值填充數組.
String names[] = { "Chenji","Yuan","Chun","Yang" };
它相當于下面功能:
String names[];
names = new String[4];
names[0]=new String("Chenji");
names[1]=new String("Yuan");
names[2]=new String("Chun");
names[3]=new String("Yang");
在編譯時不能這樣創建靜態數組:
int name[50]; / /將產生一個編譯錯誤
也不能用n e w操作去填充一個沒定義大小的數組。如:
int name[];
for (int i=0;i<9; i++) {
name[i] = i;
}
5. 表達式
J a v a語言的發展中有許多是從C語言借鑒而來的,所以J a v a的表達式和C語言非常類似。
運算符
運算符( o p e r a t o r )優先級從高到低排列如下: .
[ ] () ++ -- ! ~ instanceof * / % + - << >> >>> < > <= > == ! = & ^ && || ? : = op = ,
(2) 整數運算符
在整數運算時,如果操作數是l o n g類型,則運算結果是l o n g類型,否則為i n t類型,絕不會是
b y t e,s h o r t或c h a r型。這樣,如果變量i被聲明為s h o r t或b y t e,i + 1的結果會是i n t。如果結果超過
該類型的取值范圍,則按該類型的最大值取模。單目整數運算符是:
運算符操作
- 非
~ 位補碼
+ + 加1
- - 減1
18第一部分JSP 入門
+ +運算符用于表示直接加1操作。增量操作也可以用加運算符和賦值操作間接完成。+ +
lvalue (左值表示l v a l u e + = 1, ++lvalue 也表示lvalue =lvalue +1 (只要l v a l u e沒有副作用)。- -運
算符用于表示減1操作。+ +和- -運算符既可以作為前綴運算符,也可以作為后綴運算符。雙目
整數運算符是:
運算符操作
+ 加
- 減
* 乘
/ 除
% 取模
& 位與
| 位或
^ 位異或
< < 左移
> > 右移(帶符號)
> > > 添零右移
整數除法按零舍入。除法和取模遵守以下等式: ( a/b ) * b + ( a%b ) == a。整數算術運算的
異常是由于除零或按零取模造成的。它將引發一個算術異常,下溢產生零,上溢導致越界。例
如:加1超過整數最大值,取模后,變成最小值。一個o p =賦值運算符,和上表中的各雙目整數
運算符聯用,構成一個表達式。整數關系運算符<,>,< =,> =,= =和! =產生b o o l e a n類型的數
據。
( 3 ) 布爾運算符
布爾( b o o l e a n )變量或表達式的組合運算可以產生新的b o o l e a n值。單目運算符!是布爾非。
雙目運算符&、|和^是邏輯A N D、O R和X O R運算符,它們強制兩個操作數求布爾值。為避免
右側操作數冗余求值,用戶可以使用短路求值運算符&& 和||。用戶可以使用= =和! =,賦值
運算符也可以用& =、| =、^ =。三元條件操作符? : 和C語言中的一樣。
(4) 浮點運算符
浮點運算符可以使用常規運算符的組合,如單目運算符+ +、- -,雙目運算符+、-、* 和/,
以及賦值運算符+ =,- =,* =,和/ =。此外,還有取模運算:%和% =也可以用于浮點數,例如:
a % b和a-((int) (a/b)*b)的語義相同。這表示a % b的結果是除完后剩下的浮點數部分。只有單精度
操作數的浮點表達式按照單精度運算求值,產生單精度結果。如果浮點表達式中含有一個或一
個以上的雙精度操作數,則按雙精度運算,結果是雙精度浮點數。
(5) 數組運算符
數組運算符形式如下:
<expression> [ <expression>]
可給出數組中某個元素的值。合法的取值范圍是從0到數組的長度減1。取值范圍的檢查只
在運行時刻實施。
( 6 ) 對象運算符
雙目運算符instanceof 測試某個對象是否是指定類或其子類的實例。例如:
if (myObject instanceof MyClass) {
第二章預備知識19
MyClass anothermyObject=( MyClass) myObject;
...
}
是判定m y O b j e c t是否是M y C l a s s的實例或是其子類的實例。
(7) 強制和轉換
J a v a語言和解釋器限制使用強制和轉換,以防止出錯導致系統崩潰。整數和浮點數間可以來
回強制轉換,但整數不能強制轉換成數組或對象。對象不能被強制為基本類型。
6. Java流控制
下面幾個控制結構是從C語言借鑒的。
( 1 ) 分支結構
i f / e l s e分支結構:
if (Boolean) {
statemanets;
}
else {
statements;
}
s w i t c h分支結構:
switch(expr1) {
case expr2:
statements;
break;
case expr3:
statements;
break;
default:
statements;
break;
}
(2) 循環結構
f o r循環結構:
for (init expr1;test expr2;increment expr3) {
statements;
}
W h i l e循環結構:
While(Boolean) {
statements;
}
D o循環結構:
do
statements;
} while (Boolean);
20第一部分JSP 入門
2.1.2 Java變量和函數
J a v a的類包含變量和函數。數據變量可以是原始的類型,如i n t、c h a r等。成員函數是可執行
的過程。例如,下面的程序:
public class TestClass
public TestClass () {
i=10;
}
public void addI(int j) {
i=i+j;
}
}
Te s t C l a s s包含一個變量i和兩個成員函數,TestClass(int first)和addI(int j)。
成員函數是一個可被其他類或自己類調用的處理子程序。一個特殊的成員函數叫構造函數,
這個函數名稱一般與本類名稱相同。它沒有返回值。
在J a v a里定義一個類時,可定義一個或多個可選的構造函數,當創建本類的一個對象時,用
某一個構造函數來初始化本對象。用前面程序例子來說明,當Te s t C l a s s類創建一個新實例時,
所有成員函數和變量被創建(創建實例)。構造函數被調用。
TestClass testObject;
testObject = new TestClass();
關鍵詞n e w用來創建一個類的實例,一個類用n e w初始化前并不占用內存,它只是一個類型
定義,當t e s t O b j e c t對象初始化后,t e s t O b j e c t對象里的i變量等于1 0。可以通過對象名來引用變量
i。(有時稱為實例變量) testObject.i++;// testObject實例變量加1,因為t e s t O b j e c t有Te s t C l a s s類的
所有變量和成員函數,可以使用同樣的語法來調用成員函數a d d I:addI(10); 現在t e s t O b j e c t . i變
量等于2 1。
J a v a并不支持析構函數( C + +里的定義),因為j a v a對象無用時,有自動清除的功能,同時它
也提供了一個自動垃圾箱的成員函數,在清除對象時被調用:
Protected void finalize() { close(); }
2.1.3 子類
子類是利用存在的對象創建一個新對象的機制,比如,如果有一個H o r s e類,你可以創建一
個Z e b r a子類,Z e b r a是H o r s e的一種。
class Zebra extends Horse { int number_OF_stripes: }
關鍵詞e x t e n d s來定義對象有的子類. Z e b r a是H o r s e的子類。H o r s e類里的所有特征都將拷貝到
Z e b r a類里,而Z e b r a類里可以定義自己的成員函數和實例變量。Z e b r a稱為H o r s e的派生類或繼承。
另外,你也許還想覆蓋基類的成員函數,可用Te s t C l a s s說明,下面是一派生類覆蓋A d d I功能的
例子。
import TestClass;
public class NewClass extends TestClass {
第二章預備知識21
public void AddI(int j) {
i=i+(j/2);
}
}
當N e w C l a s s類的實例創建時,變量i初始化值為1 0,但調用A d d I產生不同的結果。
NewClass newObject;
newObject=new NewClass();
newObject.AddI(10);
當創建一個新類時,可以標明變量和成員函數的訪問層次。
public public void AnyOneCanAccess(){} public實例變量和成員函數可以由任意其他類調
用。
protected protected void OnlySubClasses(){} protected實例變量和成員函數只能被其子類調
用。
private private String CreditCardNumber; private實例變量和成員函數只能在本類里調用。
friendly void MyPackageMethod(){}是缺省的,如果沒有定義任何訪問控制,實例變量或函
數缺省定義成f r i e n d l y,這意味著可以被本包里的任意對象訪問,但其他包里的對象不可訪問。
對于靜態成員函數和變量,有時候,你創建一個類,希望這個類的所有實例都公用一個變
量。就是說,所有這個類的對象都只有實例變量的同一個拷貝。這種方法的關鍵詞為s t a t i c, 例
如:
class Block {
static int number=50;
}
所有從B l o c k類創建的對象的n u m b e r變量值都是相同的。無任在哪個對象里改變了n u m b e r的
值, 所有對象的n u m b e r都跟著改變。同樣,可以定義s t a t i c成員函數,但這個成員函數不能訪問
非s t a t i c函數和變量。
class Block {
static int number = 50;
int localvalue;
static void add_local(){
localvalue++; file://沒有運行
}
static void add_static() {
number++;//運行
}
}
2.1.4 this和s u p e r
訪問一個類的實例變量時, t h i s關鍵詞是指向這個類本身的指針,在前面的Te s t C l a s s例子中,
可以增加構造函數如下:
public class TestClass {
22第一部分JSP 入門
int i;
public TestClass() {
i = 10;
}
public TestClass (int value) {
this.i = value;
}
public void AddI(int j) {
i = i + j;
}
}
這里,t h i s指向Te s t C l a s s類的指針。如果在一個子類里覆蓋了父類的某個成員函數,但又想
調用父類的成員函數,可以用super 關鍵詞指向父類的成員函數。
import TestClass;
public class NewClass extends TestClass {
public void addI (int j) {
i = i+(j/2);
super.addI (j);
}
}
下面程序里,i變量被構造函數設為1 0,然后為1 5,最后被父類( Te s t C l a s s )設為2 5。
NewClass newObject;
newObject = new NewClass();
newObject.addI(10);
2.1.5 類的類型
迄今為止,在類前面只用了一個p u b l i c關鍵詞,其實它有下面4種選擇:
a b s t r a c t。一個a b s t r a c t類必須至少有一個虛擬函數,一個a b s t r a c t類不能直接創建對象,必須
繼承子類后才能創建對象。
f i n a l一個f i n a l類聲明了子類鏈的結尾,用f i n a l聲明的類不能再派生子類。
P u b l i c。p u b l i c類能被其他的類訪問。在其他包里,如果想使用這個類,必須先i m p o r t,否
則它只能在它定義的p a c k a g e里使用。
s y n c h r o n i c a b l e。這個類標識表示所有類的成員函數都是同步的。
2.1.6 抽象類
面向對象的一個最大優點就是能夠定義怎樣使用這個類而不必真正定義好成員函數。當程
序由不同的用戶實現時,這是很有用的,這不需用戶使用相同的成員函數名。
在j a v a里,G r a p h i c s類中一個a b s t r a c t類的例子如下:
public abstract class Graphics {
public abstract void drawLine(int x1,int y1,int x2, int y2);
public abstract void drawOval(int x,int y,int width, int height);
第二章預備知識23
public abstract void drawRect(int x,int y,int width, int height);
}
在G r a p h i c s類里聲明了幾個成員函數,但成員函數的實際代碼是在另外一個地方實現的。
public class MyClass extends Graphics { public void drawLine (int x1,int y1,int x2,
int y2) { <畫線程序代碼> } }
當一個類包含一個a b s t r a c t成員函數時,這個類必須定義為a b s t r a c t類。然而并不是a b s t r a c t類
的所有成員函數都是a b s t r a c t的。A b s t r a c t類不能有私有成員函數(它們不能被實現),也不能有靜
態成員函數。
2.1.7 接口
當確定多個類的操作方式都很相像時, a b s t r a c t成員函數是很有用的。但如果需要使用這個
a b s t r a c t成員函數,必須創建一個新類,這樣有時很繁瑣。接口提供了一種抽象成員函數的有利
方法。一個接口包含了在另一個地方實現的成員函數的收集。成員函數在接口里定義為p u b l i c和
a b s t r a c t。接口里的實例變量是p u b l i c、s t a t i c和f i n a l。接口和抽象的主要區別是,一個接口提供
了封裝成員函數協議的方法而不必強迫用戶繼承類。
例如:
public interface AudiClip {
file://Start playing the clip.
void play();
file://Play the clip in a loop.
void loop();
file://Stop playing the clip
void stop();
}
想使用Audio Clip接口的類使用i m p l e n e n t s關鍵詞來提供成員函數的程序代碼。
class MyClass implements AudioClip {
void play(){ <實現代碼> }
void loop <實現代碼> }
void stop <實現代碼> }
}
接口的優點是:一個接口類可以被任意多的類實現,每個類可以共享程序接口而不必關心
其他類是怎樣實現的。
2.1.8 包
包( P a c k a g e )由一組類( c l a s s )和界面( i n t e r f a c e )組成。它是管理大型名字空間,避免名字沖突
的工具。每一個類和界面的名字都包含在某個包中。按照一般的習慣,它的名字由“ .” 號分隔
的單詞構成,第一個單詞通常是開發這個包的組織的名稱。
定義一個編譯單元的包由p a c k a g e語句定義。如果使用p a c k a g e語句,編譯單元的第一行必
須無空格,也無注釋。其格式如下:
24第一部分JSP 入門
package packageName;
若編譯單元無p a c k a g e語句,則該單元被置于一個缺省的無名的包中。
在J a v a語言里,提供了一個包可以使用另一個包中類和界面的定義和實現的機制。用i m p o r t
關鍵詞來標明來自其他包中的類。一個編譯單元可以自動把指定的類和界面輸入到它自己的包
中。在一個包中的代碼可以有兩種方式定義自其他包中的類和界面:在每個引用的類和界面前
面給出它們所在的包的名字:
file://前綴包名法acme. project.FooBar
obj=new acme. project. FooBar( );
使用i m p o r t語句引入一個類或一個界面,或包含它們的包。引入的類和界面的名字在當前的
名字空間可用。引入一個包時,則該包所有的公有類和界面均可用。其形式如下:
// 從acme.project 引入所有類
import acme.project.*;
這個語句表示a c m e . p r o j e c t中所有的公有類被引入當前包。以下語句從acme. project包中進
入一個類E m p l o y e c _ L i s t。
file://從acme. project而引入Employee_List
import acme.project.Employee_list;
Employee_List obj = new Employee_List( );
在使用一個外部類或界面時,必須要聲明該類或界面所在的包,否則會產生編譯錯誤。
i m p o r t (引入)類包(class package)用i m p o r t關鍵詞調入指定p a c k a g e名字如路徑和類名,用*匹
配符可以調入多于一個類名。
import java.Date; import java.awt.*;
如果j a v a源文件不包含p a c k a g e,它放在缺省的無名p a c k a g e。這與源文件同目,類可以這樣
引入:
import MyClass;
J a v a系統包: J a v a語言提供了一個包含窗口工具箱、實用程序、一般I / O、工具和網絡功能
的包。
各個包的用法和類詳解在J D K自帶的文檔中都有詳細的說明,希望讀者能夠好好的看一看,
對大部分的常用包的類都熟悉了,才能更好地掌握J a v a這門技術。
在了解J a v a語言的概況以后,接下來看一看與J S P技術密切相關的三種J a v a技術:J a v a E e a n s,
J D B C,Java Servlet。
2.2 JavaBeans
J a v a B e a n s是什么?J a v a B e a s n s是一個特殊的類,這個類必須符合J a v a B e a n s規范。J a v a B e a n s
原來是為了能夠在一個可視化的集成開發環境中可視化、模塊化地利用組件技術開發應用程序
而設計的。不過,在J S P中,不需要使用任何可視化的方面,但仍然需要利用J a v a B e a n s的屬性、
事件、持久化和用戶化來實現模塊化的功能。下面分別介紹J a v a B e a n s的屬性、事件、持久化和
用戶化。
第二章預備知識25
2.2.1 JavaBeans的屬性
J a v a B e a n s的屬性與一般J a v a程序中所指的屬性,或者說與所有面向對象的程序設計語言中
對象的屬性是一個概念,在程序中的具體體現就是類中的變量。在J a v a B e a n s設計中,按照屬性
的不同作用又細分為四類: Simple, Index, Bound與C o n s t r a i n e d屬性。
1. Simple屬性
Simple 屬性表示伴隨有一對g e t / s e t方法(C語言的過程或函數在J a v a程序中稱為”方法”)的
變量。屬性名與和該屬性相關的g e t / s e t方法名對應。例如:如果有s e t X和g e t X方法,則暗指有一
個名為”X”的屬性。如果有一個方法名為i s X,則通常暗指”X”是一個布爾屬性(即X的值為
t r u e或f a l s e)。例如,在下面這個程序中:
public class alden1 extends Canvas {
string ourString= "Hello";
file://屬性名為ourString,類型為字符串
public alden1(){
file://alden1()是alden1的構造函數,與C++中構造函數的意義相同
setBackground(Color.red);
setForeground(Color.blue);
}
/* "set"屬性*/
public void setString(String newString) {
ourString=newString;
}
/* "get"屬性*/
public String getString() {
return ourString;
}
}
2. Indexed屬性
I n d e x e d屬性表示一個數組值。使用與該屬性對應的s e t / g e t方法可取得數組中的數值。該屬
性也可一次設置或取得整個數組的值。例如:
public class alden2 extends Canvas {
int[] dataSet={1,2,3,4,5,6};
// dataSet是一個indexed屬性
public alden2() {
setBackground(Color.red);
setForeground(Color.blue);
}
/* 設置整個數組*/
public void setDataSet(int[] x){
dataSet=x;
}
/* 設置數組中的單個元素值*/
public void setDataSet(int index, int x){
dataSet[index]=x;
26第一部分JSP 入門
}
/* 取得整個數組值*/
public int[] getDataSet(){
return dataSet;
}
/* 取得數組中的指定元素值*/
public int getDataSet(int x){
return dataSet[x];
}
}
3. Bound屬性
B o u n d屬性是指當該種屬性的值發生變化時,要通知其他的對象。每次屬性值改變時,這種
屬性就觸發一個P r o p e r t y C h a n g e事件(在J a v a程序中,事件也是一個對象)。事件中封裝了屬性名、
屬性的原值、屬性變化后的新值。這種事件傳遞到其他的B e a n s,至于接收事件的B e a n s應做什
么動作,由其自己定義。
當P u s h B u t t o n的b a c k g r o u n d屬性與D i a l o g的b a c k g r o u n d屬性綁定時,若P u s h B u t t o n的
b a c k g r o u n d屬性發生變化,D i a l o g的b a c k g r o u n d屬性也發生同樣的變化。例如:
public class alden3 extends Canvas{
String ourString= "Hello";
file://ourString是一個bound屬性
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
/*Java是純面向對象的語言,如果要使用某種方法則必須指明是要使用哪個對象的方法,在下面的程序中要進行點
火事件的操作,這種操作所使用的方法是在PropertyChangeSupport類中的。所以上面聲明并實例化了一個
changes對象,在下面將使用changes的firePropertyChange方法來點火ourString的屬性改變事件。*/
public void setString(string newString){
String oldString = ourString;
ourString = newString;
/* ourString的屬性值已發生變化,于是接著點火屬性改變事件*/
changes.firePropertyChange("ourString",oldString,newString);
}
public String getString(){
return ourString;
}
/** 以下代碼是為開發工具所使用的。我們不能預知alden3將與哪些其他的Beans組合成為一個應用,無法預知若
alden3的ourString屬性發生變化時有哪些其他的組件與此變化有關,因而alden3這個Beans要預留出一些接口
給開發工具,開發工具使用這些接口,把其他的JavaBeans對象與alden3掛接。*/
public void addPropertyChangeListener(PropertyChangeLisener l){
changes.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l){
changes.removePropertyChangeListener(l);
}
第二章預備知識27
通過上面的代碼,開發工具調用c h a n g e s的a d d P r o p e r t y C h a n g e L i s t e n e r方法把其他J a v a B e a n注
冊入o u r S t r i n g屬性的監聽者隊列l中,l是一個Ve c t o r數組,可存儲任何J a v a對象。開發工具也可
使用c h a n g e s的r e m o v e P r o p e r t y C h a n g e L i s t e n e r方法,從l中注銷指定的對象,使a l d e n 3的o u r S t r i n g
屬性的改變不再與這個對象有關。當然,當程序員手寫代碼編制程序時,也可直接調用這兩個
方法,把其他J a v a對象與a l d e n 3掛接。
4. Constrained屬性
J a v a B e a n s的Co n s t r a i n e d屬性是指當這個屬性的值要發生變化時,與這個屬性已建立了某種連
接的其他J a v a對象可否決屬性值的改變。Co n s t r a i n e d屬性的監聽者通過拋出P r o p e r t y Ve t o E x c e p t i o n
來阻止該屬性值的改變。
例如:下面程序中的Co n s t r a i n e d屬性是P r i c e I n C e n t s。
public class JellyBean extends Canvas{
private PropertyChangeSupport changes=new PropertyChangeSupport(this);
private VetoableChangeSupport Vetos=new VetoableChangeSupport(this);
/*與前述changes相同,可使用VetoableChangeSupport對象的實例Vetos中的方法,在特定條件下來阻
止PriceInCents值的改變。*/
......
public void setPriceInCents(int newPriceInCents) throws PropertyVetoException {
/* 方法名中throws PropertyVetoException的作用是當有其他Java對象否決PriceInCent
s的改變時,要拋出例外。*/
/* 先保存原來的屬性值*/
int oldPriceInCents=ourPriceInCents;
/**點火屬性改變否決事件*/
vetos.fireVetoableChange
("priceInCents",new Integer(OldPriceInCents), new Integer(newPriceInCents));
/**若有其他對象否決priceInCents的改變,則程序拋出例外,不再繼續執行下面的兩條語句,方法結束。若無其
他對象否決priceInCents的改變,則在下面的代碼中把ourPriceIncents賦予新值,并點火屬性改變事件*/
ourPriceInCents=newPriceInCents;
changes.firePropertyChange
("priceInCents", new Integer(oldPriceInCents),new Integer(newPriceInCents));
}
/**與前述changes相同,也要為PriceInCents屬性預留接口,使其他對象可注冊入PriceInCents否決改變監
聽者隊列中,或把該對象從中注銷
public void addVetoableChangeListener(VetoableChangeListener l){
vetos.addVetoableChangeListener(l);
}
public void removeVe