作為 Java 程序員,對(duì)于 JavaBean 也許你會(huì)說(shuō)再熟悉不過(guò)了,它貫穿在系統(tǒng)的多層中,不同的叫法有 PO、VO、DTO、POJO、DO(Domain Object)。然而它無(wú)外乎就是一個(gè) Class 類,帶上些屬性和它們的 setter/getter 方法,set/get 后面那一個(gè)字母大寫(xiě)。雖然我們現(xiàn)在很少把 JavaBean 與那個(gè)古老的 2.0 的 EJB 搞混,但為什么明明用 IDE 為屬性生成的 getter/setter 方法,應(yīng)用一運(yùn)行,還是報(bào)找不到某個(gè) bean 屬性的 setter 或 getter 方法呢?
要知道,在 Sun 的網(wǎng)站上那個(gè)關(guān)于 JavaBean 規(guī)范的 PDF 文檔可是有足足實(shí)實(shí)的 114 頁(yè)啊。難免有些規(guī)則有點(diǎn)古怪,至使知名的 IDE 都難以應(yīng)對(duì),所以我們還是有必要了解其中二三,來(lái)規(guī)范我們的 JavaBean 和解釋一些情形。
Sun 的關(guān)于 JavaBean 規(guī)范見(jiàn):http://java.sun.com/javase/technologies/desktop/javabeans/docs/spec.html,其中可下載到 JavaBean 規(guī)范的 PDF 文檔。
實(shí)際中的問(wèn)題
首
先,當(dāng)然還是要說(shuō)它的屬性及 setter/getter 方法。屬性以小寫(xiě)字母開(kāi)頭,駝峰命名格式,相應(yīng)的 getter/setter 方法是
get/set 接上首字母大寫(xiě)的屬性名。多數(shù)情況是對(duì)的,且當(dāng)前流行的 IDE(Eclipse、JBuilder) 也都認(rèn)這個(gè)死理,這里
NetBean
值得表?yè)P(yáng)一下。但要是碰到些遺留的代碼中屬性名不規(guī)范,或者有些人就是頑固,或真是對(duì)屬性命名猶豫不決時(shí)的寫(xiě)下的代碼時(shí),那還是有得你研究一下。
這里來(lái)看看 Eclipse 為幾個(gè)屬性生成的 getter/setter 方法吧:
sName(從 C 轉(zhuǎn)過(guò)來(lái)的,受匈牙利的影響,認(rèn)為 Name 是個(gè)字符串,所以加個(gè)前綴 s) getSName()/setSName(String name)
URL (平時(shí)認(rèn)為是縮略語(yǔ)/專有名詞,理當(dāng)全部大寫(xiě),這在我們對(duì)待 ID 時(shí)經(jīng)常發(fā)生的) getURL()/setURL(String url)
上
面第一個(gè)由 Eclipse 為我們生成的 getSName()/setSName(String name) 方法,參照 JavaBean
規(guī)范來(lái)說(shuō),其實(shí)是錯(cuò)誤的。如果出現(xiàn)這樣的方法,放到我們的標(biāo)簽(像 Struts 標(biāo)簽,如 <s:textfield
name="sName"/>),或是進(jìn)行 Hibernate/iBatis 那種映射時(shí),你就能收到報(bào) 找不到 sName 屬性相應(yīng)的 getter/setter 方法 那樣的錯(cuò)誤。不是明明有 getSName() 和 setSName(String name),可是方法名錯(cuò)了,正確的版本應(yīng)該是 getsName() 和 setsName(String name)。
前面首先解釋了屬性命名不規(guī)范產(chǎn)生問(wèn)題的原因,現(xiàn)在就來(lái)更仔細(xì)的了解關(guān)于 JavaBean 屬性及其 getter/setter 方法的約定,有些是硬性的。
屬性與存取訪問(wèn)的規(guī)定
為 JavaBean 創(chuàng)建屬性時(shí),必須牢記:縮略語(yǔ)通常被視為一個(gè)獨(dú)立的單詞,而不是單個(gè)字母。例如,URL 對(duì)應(yīng)的屬性名應(yīng)該用 url,相應(yīng)的 getUrl()/setUrl(),所以 ID 還是用 id 作為屬性吧,相應(yīng)的 getId()/setId()。
規(guī)
范中另一個(gè)特別的地方就是,第二個(gè)字母為大寫(xiě)的屬性名要區(qū)別對(duì)待。如果屬性名的第二個(gè)字母是大寫(xiě)的,那么該屬性名直接用作 getter/setter
方法中 get/set 的后部分,就是說(shuō)大小寫(xiě)不變。這就是為什么 sName 對(duì)應(yīng)的存取方法是 getsName()/setsName()
的原因,不能不說(shuō)這條規(guī)則很令人費(fèi)解。那就更有必要看看下面表格的規(guī)范:
屬性名/類型 | getter 方法 | setter 方法 |
xcoordinate/Double | public Double getXcoordinate() | public void setXcoordinate(Double newValue) |
xCoordinate/Double | public Double getxCoordinate() | public void setxCoordinate(Double newValue) |
XCoordinate/Double | public Double getXCoordinate() | public void setXCoordinate(Double newValue) |
Xcoordinate/Double | 不允許 | 不允許 |
student/Boolean | public Boolean getStudent() | public void setStudent(Boolean newValue) |
student/boolean | public boolean getStudent() public boolean isStudent() |
public void setStudent(boolean newValue) |
屬 性是首字母大寫(xiě),次字母小寫(xiě)是,你永遠(yuǎn)都找不到它的 getter/setter 方法的,對(duì)這個(gè)屬性的使用是會(huì)害人的。對(duì)于 boolean 類型屬性的 getter 方法是 isXxx() 還是 getXxx() 就自己決定了,isXxx() 應(yīng)該更接近于自然語(yǔ)言,更順溜些。
知道了屬性及存取方法的規(guī)定,那么你即使是面對(duì)古老代碼,在使用標(biāo)簽來(lái)引用或與 Hibernate/iBatis 等進(jìn)行映射,你就知道該填什么樣的屬性名了。
還有一個(gè)我們很少碰觸到的是關(guān)于可索引屬性的 getter/setter 方法(這方面 C# 表現(xiàn)的比 Java 要優(yōu)秀),比如有屬性
private OrderItem[] orderItem; 那它相應(yīng)的 getter/setter 除常見(jiàn)的兩個(gè)外,還有帶索引參數(shù)的兩個(gè)版本,如下:
public OrderItem[] getOrderItem();
public void setOrderItem(OrderItem[] newArray);
public OrderItem[] getOrderItem(int index);
public void setOrderItem(int index, OrderItem orderItem);
關(guān)于 Bean 導(dǎo)航
最后就是 Bean 導(dǎo)航的規(guī)范,通常用點(diǎn)記法(dot notation) 來(lái)引用屬性,同時(shí)也要注意索引屬性的訪問(wèn)。在 Web MVC 的表單中,以及標(biāo)簽中, Jarkata-Commons-BeanUtils 中用得很多??袋c(diǎn)記法的示例:
Java 代碼 | 點(diǎn)記法 |
anOrder.getAccount().getUsername() | anOrder.account.username |
anOrder.getOrderItem().get(0).getProductId() | anOrder.orderItem[0].productId |
anObject.getId() | anObject.id |
anObject.getxCoordinate() | anObject.xCoordinate |
上表應(yīng)該從右往左邊看,點(diǎn)記法中的屬性名運(yùn)行時(shí)要被解析成相應(yīng)的存取方法調(diào)用。比如像 Struts1 標(biāo)簽:
<html:text property="stocks[1].code"/>
會(huì)顯示出 FormBean 中 stocks 列表的第二個(gè)元素的 code 屬性,提交就填充到相應(yīng)的位置上去。