作者 :sonymusic 2003.05.13
六、constructorutils补遗
创建对象还有一个方法:invokeexactconstructor,该方法对参数要求
更加严格,传递进去的参数必须严格符合构造方法的参数列表。
例如:
object[] args={new integer(1), "jan"};
class[] argstype={int.class, string.class};
object obj;
//下面这句调用将不会成功,因为args[0]的类型为integer,而不是int
//obj = constructorutils.invokeexactconstructor(month.class, args);
//这一句就可以,因为argstype指定了类型。
obj = constructorutils.invokeexactconstructor(month.class, args, argstype);
month month=(month)obj;
system.out.println(beanutils.getproperty(month,"value"));
七、methodutils
与constructorutils类似,不过调用的时候,通常需要再指定一个method name的参数。
八、dynaclass/dynabean
这似乎是beanutils中最有趣的部分之一了,很简单,简单到光看这两个接口中的方法会不明白
为什么要设计这两个接口。不过看到resultsetdynaclass后,就明白了。下面是java doc中的代码:
resultset rs = ...;
resultsetdynaclass rsdc = new resultsetdynaclass(rs);
iterator rows = rsdc.iterator();
while (rows.hasnext()) {
dynabean row = (dynabean) rows.next();
... process this row ...
}
rs.close();
原来这是一个resultset的包装器,resultsetdynaclass实现了dynaclass,它的iterator方法返回一个
resultsetiterator,则是实现了dynabean接口。
在获得一个dynabean之后,我们就可以用
dynabean row = (dynabean) rows.next();
system.out.println(row.get("field1")); //field1是其中一个字段的名字
再看另一个类rowsetdynaclass的用法,代码如下:
string driver="com.mysql.jdbc.driver";
string url="jdbc:mysql://localhost/2hu?useunicode=true&characterencoding=gbk";
string username="root";
string password="";
java.sql.connection con=null;
preparedstatement ps=null;
resultset rs=null;
try {
class.forname(driver).newinstance();
con = drivermanager.getconnection(url);
ps=con.preparestatement("select * from forumlist");
rs=ps.executequery();
//先打印一下,用于检验后面的结果。
while(rs.next()){
system.out.println(rs.getstring("name"));
}
rs.beforefirst();//这里必须用beforefirst,因为rowsetdynaclass只从当前位置向前滚动
rowsetdynaclass rsdc = new rowsetdynaclass(rs);
rs.close();
ps.close();
list rows = rsdc.getrows();//返回一个标准的list,存放的是dynabean
for (int i = 0; i <rows.size(); i++) {
dynabean b=(dynabean)rows.get(i);
system.out.println(b.get("name"));
}
} catch (exception e) {
e.printstacktrace();
}
finally{
try {
con.close();
} catch (exception e) {
}
}
是不是很有趣?封装了resultset的数据,代价是占用内存。如果一个表有10万条记录,rsdc.getrows()
就会返回10万个记录。@_@
需要注意的是resultsetdynaclass和rowsetdynaclass的不同之处:
1,resultsetdynaclass是基于iterator的,一次只返回一条记录,而rowsetdynaclass是基于
list的,一次性返回全部记录。直接影响是在数据比较多时resultsetdynaclass会比较的快速,
而rowsetdynaclass需要将resultset中的全部数据都读出来(并存储在其内部),会占用过多的
内存,并且速度也会比较慢。
2,resultsetdynaclass一次只处理一条记录,在处理完成之前,resultset不可以关闭。
3,resultsetiterator的next()方法返回的dynabean其实是指向其内部的一个固定
对象,在每次next()之后,内部的值都会被改变。这样做的目的是节约内存,如果你需要保存每
次生成的dynabean,就需要创建另一个dynabean,并将数据复制过去,下面也是java doc中的代码:
arraylist results = new arraylist(); // to hold copied list
resultsetdynaclass rsdc = ...;
dynaproperty properties[] = rsdc.getdynaproperties();
basicdynaclass bdc =
new basicdynaclass("foo", basicdynabean.class,
rsdc.getdynaproperties());
iterator rows = rsdc.iterator();
while (rows.hasnext()) {
dynabean oldrow = (dynabean) rows.next();
dynabean newrow = bdc.newinstance();
propertyutils.copyproperties(newrow, oldrow);
results.add(newrow);
}
事实上dynaclass/dynabean可以用于很多地方,存储各种类型的数据。自己想吧。嘿嘿。
九、自定义的customrowsetdynaclass
两年前写过一个与rowsetdynaclass目标相同的类,不过多一个功能,就是分页,只取需要的数据,
这样内存占用就会减少。
先看一段代码:
string driver="com.mysql.jdbc.driver";
string url="jdbc:mysql://localhost/2hu?useunicode=true&characterencoding=gbk";
string username="root";
string password="";
java.sql.connection con=null;
preparedstatement ps=null;
resultset rs=null;
try {
class.forname(driver).newinstance();
con = drivermanager.getconnection(url);
ps=con.preparestatement("select * from forumlist order by name");
rs=ps.executequery();
/*
while(rs.next()){
system.out.println(rs.getstring("name"));
}
rs.beforefirst();
*/
//第二个参数表示第几页,第三个参数表示页的大小
customrowsetdynaclass rsdc = new customrowsetdynaclass(rs, 2, 5);
//rowsetdynaclass rsdc = new rowsetdynaclass(rs);
rs.close();
ps.close();
list rows = rsdc.getrows();