JavaBean規范
(1)JavaBean 類必須是一個公共類,並將其訪問屬性設置為 public ,如: public class user{ …}
(2)JavaBean 類必須有一個空的構造函數:類中必須有一個不帶參數的公用構造器,例如:public User() {…}
(3)一個javaBean類不應有公共實例變量,類變量都為private ,如: private int id;
( 4 )javaBean屬性是具有getter/setter方法的成員變量。也可以只提供getter方法,這樣的屬性叫只讀屬性;也可以只提供setter方法,這樣的屬性叫只寫屬性; 如果屬性類型為boolean類型,那么讀方法的格式可以是get或is。例如名為abc的boolean類型的屬性,它的讀方法可以是getAbc(),也可以是isAbc();
一般JavaBean屬性以小寫字母開頭,駝峰命名格式,相應的 getter/setter 方法是 get/set 接上首字母大寫的屬性名。例如:屬性名為userName,其對應的getter/setter 方法是 getUserName/setUserName。
但是,還有一些特殊情況:
1、如果屬性名的第二個字母大寫,那么該屬性名直接用作 getter/setter 方法中 get/set 的后部分,就是說大小寫不變。例如屬性名為uName,方法是getuName/setuName。
2、如果前兩個字母是大寫(一般的專有名詞和縮略詞都會大寫),也是屬性名直接用作 getter/setter 方法中 get/set 的后部分。例如屬性名為URL,方法是getURL/setURL。
3、如果首字母大寫,也是屬性名直接用作 getter/setter 方法中 get/set 的后部分。例如屬性名為Name,方法是getName/setName,這種是最糟糕的情況,會找不到屬性出錯,因為默認的屬性名是name。
所以在JavaBean命名時應該注意符合以上命名規范。
為什么JavaBean屬性名要求:前兩個字母要么都大寫,要么都小寫。
一般情況下。Java的屬性變量名都已小寫字母開頭,如:userName,showMessage等,但也存在着特殊情況,考慮到一些特定的有意思的英文縮略詞如(USA,XML等),JavaBean也允許大寫字母起頭的屬性變量名,不過必須滿足“變量的前兩個字母要么全部大寫,要么全部小寫”的要求,如:IDCode、ICCard、idCode等屬性變量名是合法的,而iC、iCcard、iDCode等屬性變量名是非法的。正是由於這個原因造成了下面這種情況:
舉個例子:
Java代碼
public class RegionDTO implements Serializable{ public String cId; public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String cName; public String getCName() { return cName; } public void setCName(String name) { cName = name; } }
封裝成List后,然后在頁面上用C標簽進行顯示
${item.cId}//報錯 RegionDTO沒有這個屬性!!!
探究原因
1、背景
本文講的普通JavaBean只是一個擁有Property(域/類變量)及其setter/getter的普通Java類。有一定Java開發經驗的人可能會知道,普通JavaBean的Property(域/類變量)的命名不能采用以下形式:aA***或者Aa***,如:"aDdress"或"Address",否則,在web應用中會報無法找到這個Property(因為根據"規則",需要找的是"ADdress"或"address")。但對於其中的原因,一般人都不明白,難道這是Sun公司當初定的規范嗎?
Java開源以后,我們終於可以解開其中的謎:
2、普通JavaBean處理涉及到相關類
在web應用中,Servlet容器或者EJB容器一般會使用java.beans包中的類來加載這些JavaBean。
BeanInfo(接口)|
SimpleInfo(類)
|
GenericBeanInfo(類)
GenericBeanInfo是JavaBean數據裝載類。
Introspector是JavaBean處理中最重要的一個處理類。
另外的一些輔助類,就不一一列舉了。
3、解密
3.1 開始在應用中,我們通常會用以下代碼來獲取一個普通JavaBean相關的信息:
BeanInfo mBeanInfo = null; try { mBeanInfo = Introspector.getBeanInfo(Person.class); } catch (IntrospectionException e) { e.printStackTrace(); }
3.2 深入
在Introspector類的getBeanInfo方法中,我們發現其中與Property處理相關的行:
private GenericBeanInfo getBeanInfo() throws IntrospectionException { …… PropertyDescriptor apropertydescriptor[] = getTargetPropertyInfo(); …… }
3.3 繼續深入
在Property處理方法中,我們發現其處理方式是根據getter/setter的方法來得到Property(域/類變量)
private PropertyDescriptor[] getTargetPropertyInfo() throws IntrospectionException{ …… if(s.startsWith("get")) obj = new PropertyDescriptor(decapitalize(s.substring(3)), method, null); …… }
接下來,最關鍵的就是下面這個方法:
public static String decapitalize(String s) { if(s == null || s.length() == 0) //空處理 return s; if(s.length() > 1 && Character.isUpperCase(s.charAt(1)) && Character.isUpperCase(s.charAt(0))){ //長度大於1,並且前兩個字符大寫時,返回原字符串 return s; } else{ //其他情況下,把原字符串的首個字符小寫處理后返回 char ac[] = s.toCharArray(); ac[0] = Character.toLowerCase(ac[0]); return new String(ac); } }