原文出自springside wiki,请留意wiki中的更新。
随着光阴推移,annotation 慢慢在开源框架中推广,泛型渐渐被程序员们用熟,加上autoboxing的小糖,springside终于离不开jdk5.0。
1.autoboxing 与 for each 循环
本来int的非object性就很无聊,在jdk5.0终于提供了autoboxing功能。这个语法简化糖,被用在了每一个地方。
for each 循环也改善了原本总要愣一下的collection遍历。不过对于非jdk基本类型,collection必须用泛型声明,如list<book>。
2. 泛型
泛型大量用于springside core中的基类,使子类更简洁,基类更强大。当然,基类是难读了,所以才需要社区花上这么长的时间来把<t>看到顺眼。
泛型使用的有两个定式:
2.1 避免强制类型转换
如果函数输入参数里含class类型,而返回值又是该class的实体,应该将该函数设为泛型函数。最典型的例子是hibernategenericdao的get() 函数
return (t) gethibernatetemplate().get(entityclass, id);
}
其中眼花缭乱的第一个<t>声明这是一个泛型函数,第2个t声明返回值为t,第三个class<t>代表 t.class。基类写的辛苦,但子类用得爽快
book book = (book)manager.get(book.class,1) 简化成了 book book = manager.get(book.class,1);
2. 2 泛型配合反射api从t获得 t.class。
最典型的例子hibernateentitydao,子类只需以下定义,即获得要管理的entity的class。
此时子类只要声明一次t,上面的book book = (book)manager(book.class,1) 就能简化成book = manager.get(1);
一举两得地既避免了强制类型转换,又声明了t.class 供框架使用,无须再在manager的构造函数或getentityclass()函数定义entityclass,。
反射的api 详见genricsutils ,精简的对上面bookmanager的定义反射代码如下:
type [] params = ((parameterizedtype) gentype).getactualtypearguments();
return (class) params[0];
泛型反射的关键是获取parameterizedtype,再调用它的getactualtypearguments()方法获得实际绑定的类型。但注意public class bookmanager<book>是不能被反射的,因为擦拭法的缘故。只有在superclass 或者成员变量(field.getgenerictype())等有函数返回parameterizedtype的时候才能成功反射,,
比如
}
public class bookaction {
private bookmanager<book> manager;
}
2.3 其他应用
1. 在xfire中,list getbooksbycategory()函数返回的结果,需要用aegis.xml 文件声明list中的元素为book.
而如果定义函数为 list<book> getbooksbycategory(),就不再需要声明,省掉xml配置文件。
3.annotation
annotation 大幅提升了java的编程模式,springside 目前运用的annotation 有:
3.1. hibernate annotation
使用hibernate annotation 代替hbm文件,因为annotation高度的默认性,典型的pojo基本上不需要定义什么,代码的简约性和可管理性大幅提高,直追ror。
另外,经过测试,annotation 完全能胜任一些比较复杂的mapping定义,如product-book的父子继承关系,order-orderitem-product的经典三角关系。
2. xfire jsr181 annotation
jsr181声明的web service,比原本用xml定义的模式节约了xml文件和配置代码的数量。
3. 声明entity类型的annotation
使用annotation 声明entity的类型,比如udeletable,auditable 等,比用接口声明的方式有更少的侵入性,详见 侵入,非侵入?interface vs annotation。
4. 三种内置annotation
jdk5.0 有suppresswarnings,deprecated和override 三种内置的annotation:
@override
此标签一方面提醒用户这是个重载函数,另一方面保证了父类函数的参数或者名字改变时,子类如果没有跟着变化,就会编译不过。
虽然有点占地方,但用处的确很大,不会哪天子类被人卖了都不知道。
所以我设置了让idea6检查所有重载函数必须加上@override标识。
@suppresswarnings("unchecked")
此标签可以让编译器忽略某种warning信息,比如减少jdk5.0的集合操作引入范型后无处不在的warning。
因为有些非jdk5.0的开源库如hibernate, 函数返回的一定是list,而不会是list<user>,这时候ide就会爆出很多warning。用suppresswarning("unchecked")可以让ide安静一些。
@deprecated
此标签以前写在javadoc里,现在提到annotation,注释已废弃的函数。用户使用该函数的话,编译时会得到"你用了废柴"的提示。
5.可变参数
用于hibernategenericdao中,简化函数接口。
比如 一个public list find(string hql, object... values),就支持了如下四种调用,避免了以前的煞费苦心的定义多种接口,然后把参数转成统一模式的大量重复定义。