免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1684 | 回复: 0
打印 上一主题 下一主题

java泛型笔记(3) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-27 16:02 |只看该作者 |倒序浏览
  
写完两个笔记,才发现才只写到官方文档的第7节~一共11节~
我非常吐血。

Collection cs = new ArrayList();
if (cs instanceof Collection) { ...} // illegal
这个是错误的,因为上个笔记讲过所有泛型类的getClass都是一样的。
所以通常问它的instanceof是没有意义的。原文如下:
Another implication of the fact that a generic class is shared among all its instances,
is that it usually makes no sense to ask an instance if it is an instance of a particular
invocation of a generic type

而且如果要强制转换:
Collection cstr = (Collection) cs
会出现警告,其实这个道理上两个笔记讲了n遍了。。

有个例子
T badCast(T t, Object o) {return (T) o; // unchecked warning
}
这个有警告,一个道理。


到现在为止,Java泛型都是用在容器里的,比如
Collection shapechildren;
或者void drawAll(Collection shapchilren) { ... }
但是java泛型不是只能用在容器里。
java泛型用在容器里比较让人容易理解,因为Collection就表示
这个容器里的每个元素都是T类型,T可以替换。
List listshape;就表示Shape类的子类的集合。
在另外一个特殊的类中,泛型也有广泛的高级应用。
那就是java.lang.Class类。
这个类在jdk1.5之前没有
例子场景:
从数据库里读取n个对象,然后放入一个容器。
比如读取一个厂里的工作人员的信息:
第一个版本:可以这样写:

interface Factory { T make(); }

public  Collection select(Factory factory, String statement) {
Collection result = new ArrayList();
//运行sql语句
for(//遍历ResultSet) {
T item = factory.make();
//利用反射填入对象T
result.add(item);
}
return result;
}

那么第一个版本有两个缺点:
1.使用不方便。
2.代码不重用。

为什么使用不方便?
我们使用这段代码只有两种方式:
select(new Factory(){
public EmplInfo make() {
return new EmplInfo();
}
}, "sql语句");

还一种方式:
class EmplInfoFactory implements Factory {
...
public EmplInfo make() {
return new EmplInfo();
}
}
然后
EmplInfoFactory emplfactory = new EmplInfoFactory();
select(emplfactory, "sql语句");

其实大家都知道,上面两个方法的本质是一样的,都是要首次建立一个实现类。
从这一点上说,使用不方便。

为什么不重用?
上个例子中我是需要EmplInfo这个对象的容器,但是如果我需要这个厂里的
Manager的容器的时候,就需要重写代码,如下:
class ManaInfoFactory implements Factory {
...
public ManaInfomake() {
return new ManaInfo();
}
}
然后
ManaInfoFactory manafactory = new ManaInfoFactory();
select(manafactory, "sql语句");
从这里可以看出代码不重用。因为我需要另外一个实现类。

以上方法发生在没有使用泛型,也没有使用java.lang.Class的时代
那么使用上了java.lang.Class会是什么样呢?
如果我们使用了jdk1.5之前的java.lang.Class,那么以上两个缺点就解决了,
当然会引入新的缺点,最终由jdk1.5中的java.lang.Class完全解决。

Collection emps = sqlUtility.select(EmpInfo.class, ”select * from emps”); //这是调用句

public static Collection select(Class c, String sqlStatement) {
Collection result = new ArrayList();
/* run sql query using jdbc */
for ( /* iterate over jdbc results */ ) {
Object item = c.newInstance();
/* use reflection and set all of item’s fields from sql results */
result.add(item);
}
return result;
}
这段代码解决了
1.使用不方便,因为不需要建立实现类
2.代码不重用,因为如果要ManaInfo的话,可以这样使用,Collection mana = sqlUtility.select(ManaInfo.class, ”select * from mana”)
这段代码引入了一个问题:
返回值是Collection并且最终赋值给了Collection.
这个做法前面几个笔记讲了n遍了,会引起警告,因为Collection是可以加入任何元素的。不仅仅是EmplInfo

所以最终解决方案,使用jdk1.5中引入的java.lang.Class
Collection emps = sqlUtility.select(EmpInfo.class, ”select * from emps”);

public static  Collection select(Class c, String sqlStatement) {
Collection result = new ArrayList();
/* run sql query using jdbc */
for ( /* iterate over jdbc results */ ) {
T item = c.newInstance();
/* use reflection and set all of item’s fields from sql results */
result.add(item);
}
return result;
}
到此,Class介绍结束。Class主要用于让代码重用。因为他可以代表任何类,传入一个EmplInfo.class,那么它就代表EmplInfo


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/105041/showart_2105593.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP