Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141195
  • 博文数量: 54
  • 博客积分: 2682
  • 博客等级: 少校
  • 技术积分: 580
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-24 20:56
文章分类
文章存档

2012年(2)

2011年(10)

2010年(28)

2009年(14)

我的朋友

分类: Java

2009-11-27 16:02:42

 

写完两个笔记,才发现才只写到官方文档的第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

阅读(665) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~