关于 JavaBean 规范你还是应该知道的二三事

作为 Java  程序员,对于 JavaBean 也许你会说再熟悉不过了,它贯穿在系统的多层中,不同的叫法有 PO、VO、DTO、POJO、DO(Domain Object)。然而它无外乎就是一个 Class 类,带上些属性和它们的 setter/getter 方法,set/get 后面那一个字母大写。虽然我们现在很少把 JavaBean 与那个古老的 2.0 的 EJB 搞混,但为什么明明用 IDE 为属性生成的 getter/setter 方法,应用一运行,还是报找不到某个 bean 属性的 setter 或 getter 方法呢?

要知道,在 Sun 的网站上那个关于 JavaBean 规范的 PDF 文档可是有足足实实的 114 页啊。难免有些规则有点古怪,至使知名的 IDE 都难以应对,所以我们还是有必要了解其中二三,来规范我们的 JavaBean 和解释一些情形。

Sun  的关于 JavaBean 规范见:http://java.sun.com/javase/technologies/desktop/javabeans/docs/spec.html,其中可下载到 JavaBean 规范的  PDF 文档。


实际中的问题


首先,当然还是要说它的属性及 setter/getter 方法。属性以小写字母开头,驼峰命名格式,相应的 getter/setter 方法是 get/set 接上首字母大写的属性名。多数情况是对的,且当前流行的 IDE(Eclipse、JBuilder) 也都认这个死理,这里 NetBean 值得表扬一下。但要是碰到些遗留的代码中属性名不规范,或者有些人就是顽固,或真是对属性命名犹豫不决时的写下的代码时,那还是有得你研究一下。

这里来看看 Eclipse 为几个属性生成的 getter/setter 方法吧:

sName(从 C 转过来的,受匈牙利的影响,认为 Name 是个字符串,所以加个前缀 s)           getSName()/setSName(String name)
URL (平时认为是缩略语/专有名词,理当全部大写,这在我们对待 ID 时经常发生的)           getURL()/setURL(String url)

上面第一个由 Eclipse 为我们生成的 getSName()/setSName(String name) 方法,参照 JavaBean  规范来说,其实是错误的。如果出现这样的方法,放到我们的标签(像 Struts 标签,如 <s:textfield name="sName"/>),或是进行 Hibernate/iBatis 那种映射时,你就能收到报 找不到 sName 属性相应的 getter/setter 方法 那样的错误。不是明明有 getSName() 和 setSName(String name),可是方法名错了,正确的版本应该是 getsName() 和 setsName(String name)。

前面首先解释了属性命名不规范产生问题的原因,现在就来更仔细的了解关于 JavaBean 属性及其 getter/setter 方法的约定,有些是硬性的。


属性与存取访问的规定

为 JavaBean 创建属性时,必须牢记:缩略语通常被视为一个独立的单词,而不是单个字母。例如,URL 对应的属性名应该用 url,相应的 getUrl()/setUrl(),所以 ID 还是用 id 作为属性吧,相应的 getId()/setId()。

规范中另一个特别的地方就是,第二个字母为大写的属性名要区别对待。如果属性名的第二个字母是大写的,那么该属性名直接用作 getter/setter 方法中 get/set 的后部分,就是说大小写不变。这就是为什么 sName 对应的存取方法是 getsName()/setsName() 的原因,不能不说这条规则很令人费解。那就更有必要看看下面表格的规范:

属性名/类型 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)

属性是首字母大写,次字母小写是,你永远都找不到它的 getter/setter 方法的,对这个属性的使用是会害人的。对于 boolean 类型属性的 getter 方法是 isXxx() 还是 getXxx() 就自己决定了,isXxx() 应该更接近于自然语言,更顺溜些。

知道了属性及存取方法的规定,那么你即使是面对古老代码,在使用标签来引用或与 Hibernate/iBatis 等进行映射,你就知道该填什么样的属性名了。

还有一个我们很少碰触到的是关于可索引属性的 getter/setter 方法(这方面 C# 表现的比 Java 要优秀),比如有属性
 
private  OrderItem[] orderItem;      那它相应的 getter/setter 除常见的两个外,还有带索引参数的两个版本,如下:

public OrderItem[] getOrderItem();
public void setOrderItem(OrderItem[] newArray);
public OrderItem[] getOrderItem(int index);
public void setOrderItem(int index, OrderItem orderItem);


关于 Bean 导航

最后就是 Bean 导航的规范,通常用点记法(dot notation) 来引用属性,同时也要注意索引属性的访问。在 Web MVC 的表单中,以及标签中, Jarkata-Commons-BeanUtils  中用得很多。看点记法的示例:

Java 代码 点记法
anOrder.getAccount().getUsername() anOrder.account.username
anOrder.getOrderItem().get(0).getProductId() anOrder.orderItem[0].productId
anObject.getId() anObject.id
anObject.getxCoordinate() anObject.xCoordinate

上表应该从右往左边看,点记法中的属性名运行时要被解析成相应的存取方法调用。比如像 Struts1 标签:

<
html:text
 property="stocks[1].code"/>

会显示出 FormBean 中 stocks 列表的第二个元素的 code 属性,提交就填充到相应的位置上去。

本文链接 https://yanbin.blog/about-javabean-spec/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

9 Comments
Inline Feedbacks
View all comments
m
m
14 years ago

写的真丑陋。

popoer
popoer
14 years ago

挺清楚的啊,平时确实很少注意这些

找个美女做老婆
14 years ago

Java高手群:Java乐园,群号:28840096 Java乐园网站:http://www.javaly.cn 欢迎Java高手加入,大家一起交流经验,相互学习,共同进步

Brian
Brian
14 years ago

@

写的不是蛮好的嘛!随便指责别人可不厚道哦

m
m
14 years ago

xcoordinate 前面的x 用来干什么的?标注类型?
Boolean 直接使用 student 做属性名显然很丑陋。
如果使用 isStudent 做属性名那么方法名可以是
isStudent() 或 getIsStudent() 。
Bean工具有不同的支持,有的不支持is开头的方法。
有人建议使用 getIsStudent() ,这样不仅能识别出所有get方法
而且可以拿出对应属性名称。
但如果都像你一样使用 isStudent() 做get方法 student做属性名。
那么Bean工具遇到 isStudent() 一类的方法 析出的属性名到底应该是
student还是 isStudent呢?哪个更具表意性呢?

隔叶黄莺
14 years ago

@m

xcoordinate 前面的 x 表示 x 坐标,用这个是方便后面说明第一个字母还是第二个字母可能出现的大小写的问题

Boolean 类型的 student 的确很丑陋,但在有些情况下还是会用到 Boolean 类型,比如与数据库的字段映射。一个是工具映射可能会这么做,还有就是它存在的道理性,数据库字段可能为 null,而只有 Boolean 才能表示出 null,当然设计规范做得好,还是用 boolean 类型好看些

至于 student 还是 isStudent,那是见仁见智,或是项目规范来约束。有些建议是 boolean 类型变量用肯定形式的词好理解,也就是 isStudent,避免 isNotFound,否定之否定就是 !isNotFound 容易让人犯迷糊。

单纯的 isStudent 固然好理解,但是它相应的 getter/setter 方法是 getIsStudent/setIsStudent 就显得有些别扭了。

严格来说,isStudent 或是 getStudent 不能说是解析出的是哪个属性: student,还是 isStudent;JavaBean 的规范是提供给我们当使用 isStudent 是解析到调用哪个方法,是 isStudent() 还是 getIsStudent(),实际上是调用的 getIsStudent(),不会是 isStudent()。

再一个有趣的现像是 Eclipse 在为属性 boolean isStudent 生成 getStudent() 和 setStudent(),这也是错误的,应该是 getIsStudent() 和 setIsStudent()。

表意的同时,我们还得遵循某些规范,虽然规范在有些时候也有丑陋的时候。

dikar
14 years ago

恩文章很不错,有些细节的地方真的还是需要注意下,
发现Unmi 技术好 人也好,分享精神也很不错。

dikar
14 years ago

Hi 老兄给你提个建议,也可能是我的错,就是貌似是你的主页上有个划词翻译,觉得有这个阅读文章不是很方便,如果只是我的浏览器的问题先说声sorry了o(∩_∩)o...哈哈

隔叶黄莺
14 years ago

@dikar

谢谢你的建议,那个划词翻译确是我主动加上去的,为的是方便阅读,其实多为中文好像是无多大意义。只是我想很多人在看网页的时候都和我一样吧,不会有用鼠标选择加亮文字的习惯,所以一直也不觉得有什么干扰,因而考虑暂实保留着现样。如有不便,还敬请谅解!