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

2012年(2)

2011年(10)

2010年(28)

2009年(14)

我的朋友

分类: Java

2009-11-27 16:01:44

 

本来jdk5之前有java.util.List这个Interface

 

是这么用的:

List myIntList = new LinkedList(); // LinkedList是实现了List Interface的类

myIntList.add(new Integer(0));

Integer x = (Integer)myIntList.iterator().next();

 

这里myIntList其实可以myIntList.add(new Object());因为声明语句就没有写出该List到底支持什么。

所以myIntList.iterator().next()返回的只能是Object,它并不知道这里面装的到底是什么具体的类。

因为这个List里既可能有Integer对象,也可能有Double对象~

 

为了不要(Integer)这个强制转换,我们有了这个:

List myIntList = new LinkedList();

这个时候,Integer x = (Integer)myIntList.iterator().next();就可以去掉强制转换写成

Integer x = myIntList.iterator.next();

因为编译器确实知道了myIntList里放的就是Integer,不会是其他。

 

这个地方要注意

List myIntList = new LinkedList();

这句话的真正含义

右边是创建一个LinkedList的对象,然后把引用给左边一个叫myIntList的名字。

理解下面两个例子就知道了:

List myIntList = new LinkedList(); //警告,不出错 myIntList可以add(Object)

List myIntList = new LinkedList(); //警告,不出错 myIntList只能add(Integer)

List myIntList = new LinkedList(); // 出错

 

事情到这里,看似所有问题都解决了,但是不尽然。慢慢道来:

class Shape {

public void say();

};

 

class Circle extends {

public void say() {

System.out.println("i am a circle");

}

};

通过上面,我们可以

Shape shape = new Circle();

shape.say(); // i am a circle.

这里表明,父类可以代表子类。

但是

List却不是List的父类

 

如果有个函数:

public void sayAll(List list) {

for(Shape s : list) {

s.say();

}

}

那么这个函数不能被这样调用:

List circleList = new List();

sayAll(circleList);

只能被这样调用:

List shapeList = new List();

sayAll(shapeList);

 

##这里详细解释为什么List不能代表List

看下面代码就知道:

List circleList = new List();

List shapeList = circleList;

shapeList.add(new Shape());

circleList.iterator().next(); //出错。

 

那么怎么解决这个问题?可以这样解决:

public void sayAll(List list) {

for(Object s : list) {

 

}

}

具体我们刚才讨论的Shape和Circle的问题可以这样写:

public void sayAll(List list) {

for(Shape s : list) {

s.say();

}

}

其中public void sayAll(List list) 就是public void sayAll(List list) 的意思

 

这个例子说明,List才是List和List的“父类”,可以传递引用。

也说明List是List的“父类”,可以传递引用,而不是List的“父类”,因为Integer extends Shape不成立

 

我们再来看一个例子来加深印象,结束这个话题。然后讨论新话题。

class Person {}

class Student extends Person{}

public class Census {

public static void addRegistry(Map registry) { ... }

};

 

Map allDrivers = ...

Census.add(allDrivers);

 

我们下一个话题,先由这个引起:

我们说过,如果

List是List的“父类”

那么会出现一个矛盾:

List circleList = new List();

List shapeList = circleList; //错误

shapeList.add(new Shape());

circleList.iterator().next(); //出错。

 

那么List确实是List的“父类”,会有这个矛盾不?同样有,如下:

List circleList = new List();

List list= circleList; //正确

list.add(new Shape()); //错误

为什么list不能加新元素?

因为list里的元素类型已经定义好了,是?,不是任何类型,所以不能加入任何类型的元素。

所以如下方法是不能使用的:

static void fromArrayToCollection(Object[] a, Collection c) {

for (Object o : a) {

c.add(o); // compile time error 因为c不能加入元素

}

}

 

但是我们想要在List里加入元素如何弄呢?一个例子概括如下:

static void fromArrayToCollection(T[] a, Collection c) {

for (T o : a) {

c.add(o); // correct

}

}

那么这样,c这个Collection就能加入东西了,加入的东西必须是T类,看例子:

Object[] oa = new Object[100];

Collection co = new ArrayList();

fromArrayToCollection(oa, co);// T inferred to be Object

 

String[] sa = new String[100];

Collection cs = new ArrayList();

fromArrayToCollection(sa, cs);// T inferred to be String

fromArrayToCollection(sa, co);// T inferred to be Object

 

Integer[] ia = new Integer[100];

Float[] fa = new Float[100];

Number[] na = new Number[100];

Collection cn = new ArrayList();

fromArrayToCollection(ia, cn);// T inferred to be Number

fromArrayToCollection(fa, cn);// T inferred to be Number

fromArrayToCollection(na, cn);// T inferred to be Number

fromArrayToCollection(na, co);// T inferred to be Object

fromArrayToCollection(na, cs);// compile-time error

 

 

到现在为止,上面一共讲了两个jdk1.5中新的事物

List list = new LinkedList(); // wildcards

static void fromArrayToCollection(T[] a, Collection c)

 

那么看下面两个例子,他们做的事情都是一样的,但是分别用了这两个方法:

interface Collection {

public boolean containsAll(Collection c);

public boolean addAll(Collection

}

 

interface Collection {

public boolean containsAll(Collection c);

public boolean addAll(Collection c);

}

 

他们都做两件事:判断任意类的容器是不是在本身这容器里。加入E子类的容器到本身的容器里。

 

也可以同时都用上两个新东西:

class Collection {

public static void copy(List dest, List src){}

}

 

或者写成

class Collection {

public static void copy(List dest, List src){}

}

 

作为总结这两个新的java特性,举出一个复杂例子:

 

static List> history = new ArrayList>();

 

public void drawAll(List shapes) {

history.addLast(shapes);

for(Shape s : shape) {

s.draw(this);

}

}

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